Thứ Sáu, 2 tháng 8, 2013

Integer Arithmetic in ASM

Introduction

Assembly language có các lệnh để di chuyển bits vòng quanh bên trong operands. Shift và rotate instructions, các lệnh này hữu ích khi điều khiển các thiết bị phần cứng, mã hóa dữ liệu, và implementing high-speed graphics. Bài viết này giải thích cách thực hiện shift và rotate operations và làm thế nào để thực hiện các phép tính nhân chia sử dụng shift operations.

Tiếp theo chúng ta sẽ tìm hiểu các lệnh nhân chia đối với số nguyên. Intel phân loại các lệnh theo các phép tính có dấu và không dấu. Sử dụng những lệnh này, chúng tôi show cách làm thế nào để chuyển mathematical expressions từ C++ vào trong assembly language. Compilers chia các expressions phức tạp thành một chuỗi các lệnh máy rời rạc. Nếu bạn học cách translate các phép tính toán trong assembly language , bạn có thể hiểu hơn về cách compilers làm việc, và bạn sẽ có thể optimize assembly language. Bạn sẽ học về cách các luật ưu tiên và register optimization làm việc tại mức độ mã máy.

Các phép tính với các số nguyên có độ dài tùy ý (còn được biết đến như bignums) không được hỗ trợ bởi tất cả các ngôn ngữ bậc cao. Nhưng trong assembly language , bạn có thể sử dụng các lệnh như ADC (add with carry) và SBB (subtract with borrow) để làm việc với các số nguyên với bất kì kích thước nào. Trong loạt bài viết , tôi sẽ còn trình bày các lệnh chuyên biệt để thực hiện các phép tính trên packed decimal integers và integer strings.

Shift and Rotate Instructions

Shifting nghĩa là di chuyển các bit sang bên phải và trái bên trong một operand. Bảng dưới đây là một tập hợp các lệnh mà x86 cung cấp để di chuyển các bits, tất cả ảnh hưởng đến cờ OF và CF.

Logical Shifts and Arithmetic Shifts

Có hai cách để shift các bits của một operand. Thứ nhất, logical shift, lấp vị trí mới được tạo ra với zero. Minh họa dưới đây, một byte được dịch qua phải một vị trí. Hãy nói cách khác, mỗi bit được di chuyển đến vị trí bit thấp hơn tiếp theo. Chú ý rằng bit 7 được gán bằng 0:
Minh họa phía dưới shows một single logical right shift trên một giá trị nhị phân 11001111, kết quả là 01100111. Bit thấp nhất được dịch vào trong cờ CF:

Một kiểu shift khác được gọi là arithmetic shift. Vị trí mới được tạo được lấp với một bản sao của bit dấu của số ban đầu:


Ví dụ binary 11001111, có bit dấu là 1. Khi thực hiện shifted arthimetically 1 bit qua phải, nó trở thành 11100111
SHL Instruction

SHL (shift left) instruction thực hiện một logical left shift trên destination operand, lấp bit thấp nhất với số 0. Bit cao nhất được chuyển vào CF :

Nếu như bạn shift 11001111 sang trái 1 bit , nó trở thành:

Operand đầu tiên trong SHL là destination  và operand thứ 2 là shift count:

SHL    destination, count 

Danh sách dưới đây liệt kê các kiểu operands được cho phép bởi lệnh này:

SHL   reg, imm8
SHL  mem, imm8
SHL  reg, CL
SHL  mem, CL

x86 processors cho phép imm8 là bất kì số nguyên nào trong khoảng từ 0 đến 255. CL register cso thể chứa một shift count. Formats này còn được áp dụng cho SHR, SAL, SAR, ROR, ROL, RCR, và RCL instructions. 

Ví dụ  Trong các lệnh dưới đây , BL được shifted qua trái 1 đơn vị. Bit cao nhất được copy vào trong CF và bit thấp nhất được gán bằng 0. 

mov  bl, 8Fh                              ; BL = 10001111b
shl    bl, 1                                  ; BL = 00011110b, CF = 1

Multiple Shifts  Khi một giá trị được shifted qua trái nhiều lần, CF chứa bit cuối cùng đực shifted ra ngoài MSB. Trong ví dụ dưới đây, CF không giữ giá trị bit 7 mà là bit 6:

mov   al, 10000000b
shl     al, 2                                            ; al = 00000000b, CF =0

Tương tự, khi một giá trị được shifted sang phải nhiều lần, CF chứa bit cuối cùng được shifted ra ngoài LSB. 

Bitwise Multiplication SHL có thể thực hiện phép nhân cho lũy thừa của 2. Shifting bất kì operand sang trái n bits sẽ nhân operand với 2 ^ n. Cho ví dụ, shifting số 5 sang trái 1 bit sẽ cho kết quả là 5 x 2^1 = 10

Nếu binary 00001010 (decimal 10) được dịch sang trái 2 bits, kết quả sẽ giống như việc ta nhân 10 với 2^2:


SHR Instruction

SHR (shift right) instruction thực hiện một logical right shift trên destination operand, thay thế bit cao nhất với 0. Bit thấp nhất được sao chép vào trong CF, và giá trị đang có của CF bị mất đi:

SHR sử dụng cùng các định dạng lệnh như SHL. Trong ví dụ sau, 0 từ bit thấp nhất trong AL được sao chép vào trong AL, và bit cao nhất được lấp bằng zero. 

Multiple Shifts  Trong một phép toán shift nhiều lần, bit cuối cùng được shifted ngoài LSB là giá trị trong CF:

Bitwise Division   Logically shifting một unsigned integer sang phải n bits chia operand đi lũy thừa của 2. Trong statements sau, chúng ta chia 32 cho 2^1, kết quả là 16:

Trong ví dụ sau , 64 chia cho 2^3:
Phép chia các số có dấu thông qua shifting được thực hiện bằng cách sử dụng SAR instruction bởi vì nó bảo vệ bit dấu của số. 

SAL và SAR Instructions

SAL (shift arithmetic left) instruction hoạt động giống như lệnh SHL. Đối với mỗi shift count, SAL shifts mỗi bit trong destination operand sang vị trí cao nằm bên cạnh. Bit được thấp nhất được gán bằng 0. Bit cao nhất được chuyển đến CF, bit nằm trong CF bị bỏ đi:

Nếu bạn shift binary 11001111 sang trái 1 bit, nó trở thành 10011110:
SAR (shift arthimetic right) instruction thực hiện một right arithmetic shift trên destination của nó:

Operands của SAL và SAR giống như opearands của SHL và SHR. Shift có thể được lặp lại, dựa trên counter trong operand thứ 2:

SAR   destination, count

Ví dụ sau đây show cách SAR duplicates bit dấu. AL là một giá trị âm trước và sau khi nó được shifted qua phải:


Signed Division Bạn có thể chia một signed operand cho lũy thừa của 2 , sử dụng SAR instruction. Trong ví dụ sau, -128 chia cho 2^3. Kết quả là -16:

Sign-Exten AX into EAX  Giả sử AX chứa một giá trị nguyên có dấu và bạn muốn extend dấu của nó trong EAX. Thứ nhất, thứ nhất shift EAX sang trái 16 bits, sau đó shift arithmetically sang phải 16 bits.

Không có nhận xét nào:

Đăng nhận xét