Làm thế nào tôi có thể đặt mã điều kiện trong ngôn ngữ lắp ráp?


7

Tôi muốn kiểm tra các dấu hiệu biến. Nói cách khác, tôi muốn biết câu trả lời cho dù một biến là dương hay âm. Làm thế nào tôi có thể viết các điều kiện if-then-other bằng ngôn ngữ hợp ngữ?

  if X > 0 
      goto A
  else 
      goto B

Tôi đang sử dụng PtubC16f87x

Để làm cho câu hỏi của tôi trở nên tổng quát hơn, nếu bạn biết bạn có thể đưa ra câu trả lời cho các câu hỏi dưới đây không?

Tôi.)

    if X > Y 
        goto A
    else 
        goto B

ii.)

    if X >= Y 
        goto A
    else 
        goto B

iii.)

    if X != Y 
        goto A
    else 
        goto B

2
Tôi nhớ mã trình biên dịch mã z80, nhưng bạn đạt được sự so sánh với phép trừ và kiểm tra giá trị mang và bit 0
clabacchio

Câu trả lời:


11

Tôi không quen thuộc với vi điều khiển PIC, vì vậy tôi sẽ đưa ra câu trả lời tổng quát hơn. (chỉnh sửa: Câu trả lời cụ thể cho PIC được thêm ở cuối bài này)

Đặc biệt là các bộ vi điều khiển nhỏ hơn, như 8 bit và các dẫn xuất của chúng, bị giới hạn trong những gì chúng có thể làm trong một lệnh đơn. Một lệnh có thể chứa địa chỉ đích cho một bước nhảy, nhưng không phải là hai trong số chúng, vì vậy then-elselà hết. Bạn chỉ có if-thenmột phần, nhưng thế là đủ. Có hai cách tiếp cận. Một số bộ điều khiển cho phép bạn chuyển đến một địa chỉ nhất định nếu một điều kiện được đáp ứng, những điều kiện khác chỉ cho phép bạn bỏ qua hướng dẫn tiếp theo. Trong trường hợp trước, mã của bạn sẽ trông như sau:

              if-test-succeeds goto test-success
test-failed   first instruction of `else` block
              ...
              goto continue
test-success  first instruction of `then` block
              ...
continue      first instruction after if-then-else

Nếu bạn chỉ có thể bỏ qua hướng dẫn tiếp theo, bạn sẽ viết một cái gì đó như

              if-test-succeeds skip next instruction
              goto test-failed
test-success  first instruction of `then` block
              ...
              goto continue
test-failed   first instruction of `else` block
              ...
continue      first instruction after if-then-else  

Bản thân bài kiểm tra cũng có khả năng hạn chế. Giống như bạn không thể vượt qua hai số để so sánh chúng. Những gì bạn làm là tải bộ tích lũy với số thứ nhất và trong hướng dẫn tiếp theo trừ đi số thứ hai. Điều này sẽ khiến các mã điều kiện như số 0 và cờ mang được đặt / xóa. Hướng dẫn có điều kiện sẽ kiểm tra cho những lá cờ. Vì vậy, nếu bạn muốn viết if A = B then do-equal else do-not-equalnày sẽ trở thành

              load accumulator with A
              subtract B from accumulator
              if zero-flag set goto do-equal
do-not-equal  first instruction of `else` block
              ...
              goto continue
do-equal      first instruction of `then` block
              ...
continue      first instruction after if-then-else

Quan trọng: hướng dẫn tập lệnh sẽ cho bạn biết mã điều kiện nào sẽ bị ảnh hưởng bởi một lệnh đã cho. Chẳng hạn, trong Z80, ldlệnh (đối với "bộ tích lũy tải") sẽ không thay đổi bất kỳ cờ nào. Vì vậy, ở đây tải bộ tích lũy là không đủ để xác định nếu dữ liệu bằng không.


chỉnh sửa
OK, vì vậy tôi đã thực hiện một số nghiên cứu và tôi thấy như sau:
PIC chỉ có 2 hướng dẫn nhảy có điều kiện BTFSSBTFSC.

BTFSS : Kiểm tra bit F, Bỏ qua nếu đặt
Cú pháp: BTFSS f, b
trong đó f là thanh ghi [0..127]
và b là bit trong thanh ghi được kiểm tra [0..7]
Mô tả: Nếu bit trong thanh ghi là 0hướng dẫn tiếp theo được thực hiện. Nếu bit là 1lệnh tiếp theo bị loại bỏ và NOPthay vào đó sẽ được thực thi.

BTFSC : Bit Test F, Skip if Clear
Cú pháp: BTFSC f, b
trong đó f là thanh ghi [0..127]
và b là bit trong thanh ghi được kiểm tra [0..7]
Mô tả: Nếu bit trong thanh ghi là 1hướng dẫn tiếp theo được thực hiện. Nếu bit là 0lệnh tiếp theo bị loại bỏ và NOPthay vào đó sẽ được thực thi.


6

Để kiểm tra xem một số nguyên có âm không, bạn chỉ cần kiểm tra bit trên cùng. Nếu bit trên cùng là 1, thì nó âm.

Bây giờ, đối với số nguyên 8 bit trên clabacchio 8 bit được đề cập, bạn có thể sử dụng phép trừ để thực hiện kiểm tra. Tuy nhiên, theo nguyên tắc chung, điều này không tối ưu:

  1. PIC có các hướng dẫn btfsc và btfss hữu ích, bạn có thể sử dụng để kiểm tra trực tiếp bit trên cùng, như rokjarc đã đề cập. Điều này thậm chí có thể được sử dụng để kiểm tra các số nguyên 16 và 32 bit (và thậm chí là số float!)

Điều này đáng chú ý, ngay cả trong C, bởi vì tôi đã thấy trình biên dịch Microchip C tạo mã ngu ngốc. Khi kiểm tra xem số nguyên 16 bit có lớn hơn 0 hay không, họ sẽ tạo ra tập hợp để trừ số nguyên từ 0 và kiểm tra các cờ, thay vì chỉ sử dụng btfss.

Vì vậy, bất cứ khi nào tôi viết PIC C, tôi luôn kiểm tra đầu ra lắp ráp để xem nó có hợp lý không. Và sau đó, thông thường, viết macro để thực hiện các hoạt động. (BTW, tôi thực sự chưa kiểm tra các macro này, chúng chỉ ở trên đỉnh đầu của tôi).

#define IF_NEGATIVE_16_BIT(x) if (*((int8*)((&x)+1)) & 0x80)
#define IF_NEGATIVE_32_BIT(x) if (*((int8*)((&x)+3)) & 0x80)
  1. Các vi điều khiển khác có hướng dẫn AND. Chỉ VÀ VÀ byte trên cùng của số nguyên với 0x80. Nếu cờ zero được đặt, thì số nguyên không âm.

6

Để thực hiện so sánh số nguyên và hầu hết mọi thứ khác trong ngôn ngữ lắp ráp, bạn phải hiểu cách các số được biểu diễn.

Hầu hết các biến trong một hệ thống nhúng nhỏ là không dấu, hoặc ít nhất là nên. Các lập trình viên ngôn ngữ cấp cao đã quen với các hệ thống lớn hơn có xu hướng không nghĩ về điều này và sử dụng các biến đã ký khi chỉ cần không dấu. Không được ký thường dễ làm việc hơn ở cấp độ thấp.

Mã của bạn là dành cho PIC 16, vì vậy tôi sẽ cho rằng bạn đang sử dụng trình biên dịch MPASM. Tôi có một loạt các macro và các phương tiện khác để trợ giúp những thứ như so sánh cường độ trong tệp chung của tôi bao gồm tệp STD.INS.ASPIC , một phần trong môi trường phát triển PIC của tôi . Cụ thể, các macro SKIP_WLE (bỏ qua nếu W nhỏ hơn hoặc bằng) và SKIP_WGT (bỏ qua nếu W lớn hơn) các macro để so sánh các số không dấu.

PIC có một bit trạng thái mang, được gọi là C, là đầu ra mang của ALU. Bit này có thể được kiểm tra sau khi cộng hoặc trừ để xem liệu có thực hiện được bit cao của ALU không. Cách trừ hoạt động với số bổ sung twos, bit C trở thành bit không vay sau khi trừ. Để làm cho mọi thứ phức tạp hơn, các lệnh trừ PIC trừ đi thanh ghi W khỏi toán hạng, không phải theo cách khác. Bạn phải thực hiện một số môn thể dục dụng cụ tinh thần để theo dõi C không được vay và những gì thực sự bị trừ khỏi những gì và do đó một khoản vay thực sự có nghĩa là gì. Tôi đã làm tất cả điều này một lần và gói gọn kết quả trong hai macro đơn giản này vì vậy tôi không phải suy nghĩ về nó mỗi lần và có cơ hội làm hỏng nó. Trên PIC 16, SKIP_WLE biến thành một lệnh BTFSS STATUS, C và SKIP_WGT biến thành BTFSC STATUS, C.

Đây là cách bạn sẽ sử dụng các macro này trong mã:

maxok bằng 37; mức bể tối đa OK
         ...
;
; Kiểm tra mức bể và chạy thói quen ngoại lệ nếu nó là
; quá cao.
;
         bankel tanklev; thiết lập ngân hàng để truy cập vào TANKLEV
         Movf tanklev, w; có được mức đầy đủ của xe tăng
         sublw maxok; so với mức bình thường tối đa
         Skip_wle; mức bể nằm trong phạm vi?
         goto ohcrap; không
;
; Mức bể là trong giới hạn hoạt động bình thường.
;

Có rất nhiều điều hữu ích khác trong STD.INS.ASPIC. Tôi cũng có một bộ tiền xử lý bổ sung nhiều tính năng hữu ích cho ngôn ngữ MPASM. Ví dụ, nó có thể thực hiện phép toán dấu phẩy động tại thời điểm xây dựng, có thể thực hiện thao tác chuỗi thực để xây dựng tên biểu tượng, có khả năng macro linh hoạt hơn và nhiều hơn nữa.


6

Bây giờ tôi sẽ trả lời phần đầu của câu hỏi.

Bạn không đề cập đến loại X - giả sử nó đã được ký. Đã ký char có b.7 == 1 khi âm, vì vậy chúng ta chỉ phải kiểm tra trạng thái của bit đó.

//checking if bit 7 of X is cleared (X.7 == 0)
BTFSC   X,7    //if X.7 == 0 (X is positive) we'll skip the next instruction
GOTO    B
GOTO    A

//checking if bit 7 of X is set (X.7 == 1)
BTFSS   X,7    //if X.7 == 1 (X is negative) we'll skip the next instruction
GOTO    A
GOTO    B

Đây là một liên kết đến hướng dẫn hay: Hướng dẫn về các cấu trúc lập trình hội PIC phổ biến

Ví dụ trên có thể được tìm thấy trên trang 7.

Cố gắng tự mình tìm ra phần còn lại của câu trả lời. Gợi ý: nhận xét của clabacchio rất hữu ích.


Có phải giống như: Jason Thweatt. "Hướng dẫn về các cấu trúc lập trình hội PIC phổ biến". ucpic.byethost7.com/Doads/ApuntesAssembler/Apunte2.pdf ?
davidcary

Đúng! cảm ơn vì đã ngẩng cao đầu, tôi không nhận thấy liên kết cũ bị sập. sẽ chỉnh sửa.
Rok Jarc

0

So sánh 16 bit

  • X = XH: XL các byte Hi và Lo của biến RAM X,
  • Y = YH: YL các byte Hi và Lo của biến RAM Y.

Tất cả các giá trị không dấu.

; if( y < x )
  movfw XL
  subwf YL,w
  movfw XH
  skpc ; c=0 indicates a borrow we need to propagate.
    incfsz XH,w ; handle XH=0xff correctly, unlike ``incf XH,w''.
      subwf YH,w
  skpnc
    goto else
; then:
; /* y is less than x */
  ...
  goto endif
else:
; /* y is NOT less than x */
  ...
endif:

; if( x <= y )
  movfw XL
  subwf YL,w
  movfw XH
  skpc ; c=0 indicates a borrow we need to propagate.
    incfsz XH,w ; handle XH=0xff correctly, unlike ``incf XH,w''.
      subwf YH,w
  skpc
    goto else
; then:
; /* x is less than or equal to y */
  ...
  goto endif
else:
; /* x is NOT less than or equal to y */
  ...
endif:

; if(X == Y)
  movf XH,w
  xorwf YH,w
  skpz
  goto else
  movf XL,w
  xorwf YL
  skpz
  goto else
; then:
; /* X equals Y */
  ...
  goto endif
else:
; /* X is not the same as Y */
  ...
endif:

Các lập trình viên ngôn ngữ hội thường thay đổi các thẻ "other:" và "endif:" thành nhãn duy nhất (và hy vọng mô tả) cho mỗi câu lệnh if. Có lẽ một cái gì đó như "then_in_n normal_range:", "other_outside_n normal_range:" và "finish_range_handling:". (Không giống như các ngôn ngữ cấp cao hơn như Pascal và BASIC nơi chúng tôi sử dụng cùng một từ "sau đó" và "khác" và "endif" cho mỗi câu lệnh if.).

Đoạn mã trên chỉ hoạt động khi cả X và Y đều nằm trong RAM - PIC16f87x yêu cầu các hướng dẫn khác nhau để so sánh X với giá trị không đổi.

Một cách để xử lý các số đã ký 16 bit là trước tiên lật bit cao

movlw 0x80
xorwf XH,w
xorwf YH,w

sau đó sử dụng mã so sánh trên. Sau đó, khôi phục các giá trị ban đầu bằng cách lật lại bit cao

movlw 0x80
xorwf XH,w
xorwf YH,w

.

ps Bạn thường có thể nhận được câu trả lời nhanh hơn nhiều cho các câu hỏi về PIC16f87x bằng cách tìm kiếm trang web PIClist http://piclist.com/ và Microchip wiki http://microchip.wikidot.com . Để so sánh ngôn ngữ lắp ráp, xem trang "So sánh ngôn ngữ hội" trên wiki MicrochipPhương pháp toán so sánh vi điều khiển PIC trên trang web PIClist (trong đó ở trên là một trích xuất nhỏ).

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.