Thiết kế chương trình ngôn ngữ hội


7

Đây là một vấn đề bài tập về nhà và tôi đã cố gắng giải quyết chuyện này suốt đêm qua nhưng tôi vẫn là một người mới trong ngôn ngữ hội.

Đừng cho tôi giải pháp đầy đủ, chỉ cho tôi một gợi ý.

Thiết kế chương trình Ngôn ngữ hội ARM sẽ kiểm tra giá trị 32 bit được lưu trữ trong R1 và đếm số chuỗi liên tiếp trong 1 giây. Ví dụ: giá trị: 01110001000111101100011100011111chứa sáu chuỗi 1s.

Viết giá trị cuối cùng vào thanh ghi, R2.

Bây giờ, thuật toán tôi nghĩ là đọc từng ký tự một, và tăng thêm i1 mỗi lần nó phải đối mặt với 2 giây liên tục. Nhưng làm thế nào để làm điều đó trong ngôn ngữ hội?


2
Đoạn cuối của bạn có vẻ hơi lạc đề với tôi. Nhưng tôi không chắc bạn muốn có bao nhiêu gợi ý, vì vậy tôi sẽ chỉ nói điều này: Điều quan trọng cần tìm là khi hai bit liền kề khác nhau, không giống nhau. Hãy suy nghĩ về những gì sẽ xảy ra nếu bạn lấy một bản sao của dữ liệu trong R1, thay đổi nó một chút và XOR nó với giá trị ban đầu.
Dave Tweed

1
Trong ISA của bạn chắc chắn phải có một lệnh để bit xoay qua carry. Đầu tiên bạn xóa cờ mang. Và sau đó bạn có thể chỉ cần xoay nó sang trái / phải và kiểm tra giá trị của cờ mang. Sau đó, giá trị mang sẽ nhập vào máy trạng thái của bạn. Mã một máy trạng thái đơn giản cho điều đó.
Tiêu chuẩn Sandun

Và hãy nhớ rằng một thanh ghi chứa 0 và 1 bit, không phải các ký tự 0 và 1. Bạn nên xem các toán tử bit khôn ngoan, bao gồm các hướng dẫn thay đổi.
Joe Hass

2
Nếu bạn chưa quen với asm nhưng đừng nói mã C: viết mã C để giải quyết vấn đề, sau đó (hand-) dịch nó sang asm từng bước.
Wouter van Ooijen

3
@WoutervanOoijen Tôi thậm chí đã tìm thấy một chương trình tự động dịch C-> asm này ...
markrages

Câu trả lời:


10

Viết một vòng lặp để dịch từ trái sang phải (không quan trọng) cho đến khi từ đó là tất cả các số không. Cờ mang cho bạn giá trị của bit tiếp theo.

Nếu carry là 1và carry trước bằng 0 thì bạn đang bắt đầu một chuỗi 1s mới. Sau đó đặt cờ trước đó là cờ đầu tiên. (Tôi cho rằng bằng cách tiếp giáp bạn có nghĩa là ít nhất 2.)

Nếu thực hiện 1previous-was-a-first-oneđược đặt, bạn có một chuỗi liền kề và tăng bộ đếm của bạn. Xóa previous-was-a-first-onecờ.

Nếu mang 0thì rõ previous-was-a-first-one.

chỉnh sửa
Rõ ràng "tiếp giáp" không yêu cầu nhiều hơn 1 bit, và sau đó nó thậm chí còn đơn giản hơn:

Set `previous' to `0`.
Shift left until word is all zeros.
If `carry` = `1` and `previous` = `0` increment counter.
Set `previous` to `carry`.

1
Tại sao bạn lại đoán "ít nhất là 2" khi ví dụ anh ấy đưa ra bao gồm một chuỗi chỉ có 1?
Dave Tweed

4
@Dave - Có một '1' bị cô lập trong ví dụ, nhưng anh ta không nói nếu anh ta coi đó là một chuỗi liền kề. Bây giờ tiếng Anh thậm chí không phải là ngôn ngữ thứ hai của tôi, mà là ngôn ngữ thứ ba của tôi, vì vậy hãy đồng ý với tôi, nhưng IMO "tiếp giáp" phỏng đoán ít nhất hai lần liên tiếp.
stevenvh

3
@Dave - Tiếp giáp : 1. "chạm dọc theo bên hoặc ranh giới; tiếp xúc" 2. "liền kề vật lý; lân cận" 3. "trước hoặc theo thời gian"
stevenvh

1
vâng, anh ấy đã làm - anh ấy nói rằng ví dụ này bao gồm sáu chuỗi, vì vậy rõ ràng anh ấy đang đếm số '1' bị cô lập
Dave Tweed

1
@Dave - Quả thực anh đã làm. "Tiếp giáp" dường như là một khái niệm có khả năng co giãn cao :-). Cập nhật câu trả lời của tôi. Cảm ơn vì bạn đã phản hồi.
stevenvh

1

Đây là một giải pháp lặp lại theo số lượng chuỗi, thay vì số bit trong từ. Vì tôi không thực sự quen thuộc với ngôn ngữ lắp ráp ARM, tôi sẽ cung cấp nó trong C. Vì nó chỉ sử dụng các toán tử bitwise, nên nó sẽ dịch trực tiếp khá nhiều vào mã lắp ráp.

int nstrings (unsigned long int x)
{
   int result = 0;

   /* convert x into a word that has a '1' for every transition from
    * 0 to 1 or 1 to 0 in the original word.
    */
   x ^= (x << 1);

   /* every pair of ones in the new word represents a string of ones in
    * the original word. Remove them two at a time and keep count.
    */
   while (x) {
     /* remove the lowest set bit from x; this represents the start of a
      * string of ones.
      */
     x &= ~(x & -x);
     ++result;

     /* remove the next set bit from x; this represents the end of that
      * string of ones.
      */
     x &= ~(x & -x);
   }
   return result;
}

1

Chỉ cần gợi ý như đã hỏi. Bạn cần thay đổi từng bit, điều này có thể được thực hiện bằng shiftingsố đến right. Trước khi dịch chuyển, kiểm tra giá trị của bit ngoài cùng bên phải, điều này có thể đạt được bằng thao tác ANDvới chi phí 1. Sử dụng một số temp để lưu giá trị cuối cùng được kiểm tra, để tăng bộ đếm trên "cạnh tăng" tức là khi giá trị trước đó thay đổi từ 0 thành 1, trong mã giả

SET T1=0
SET CNT=0
WHILE INPUT != 0 DO
    IF INPUT AND 1 != 0 AND T1 == 0 INC CNT
    T1 =  INPUT AND 1
    RIGHT SHIFT INPUT
END WHILE

0
  1. Một thanh ghi X đã cho sẽ có kết quả. Ban đầu nó bằng không.
  2. Lấy giá trị ban đầu để được xử lý và lưu trữ nó trong hai thanh ghi, giả sử A và B.
  3. Xoay A sang phải một bit, thực hiện XOR của A với B, đặt kết quả vào A.
  4. Đắp mặt nạ 1h cho A, đặt kết quả vào B.
  5. Tổng B đến X.
  6. Chuyển một bit sang phải và, nếu không bằng 0, lặp sang bước 4
  7. Chia X cho 2 (thay đổi đúng một bit)

Điều này hoạt động vì kết quả của XOR trong bước 3 sẽ có một cặp 1 tại mỗi điểm có chuyển đổi. Vì vậy, nếu sau đó bạn đếm xem bạn có bao nhiêu 1 và chia cho 2, bạn sẽ có bao nhiêu lần chuyển đổi. Cung cấp cho bạn số khối của các giá trị liên tiếp.

Bây giờ, nếu X kết quả bằng 0, bạn có tất cả 1 hoặc tất cả 0. Vì vậy, bạn có thể bắt đầu bằng cách kiểm tra xem giá trị ban đầu có bằng 0 không và trả về ngay lập tức bằng 0 trong trường hợp đó, thậm chí không chạy các bước trên. Nếu không, và X bằng 0, bạn trả về 1. Nếu không, bạn chia nó cho 2 lần nữa (vì số khối có 1 phải bằng một nửa số khối riêng biệt, tất nhiên).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.