x / 2 + 100 * (a + b) - 3 / (c + d) + e * e trong lắp ráp

Oct 21 2020

viết thuật toán cho: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e biết rằng: a, c - word, b, d - byte, e - doubleword, x - qword

    mov eax, dword [x]
    mov edx, dword [x + 4] ; edx:eax = x
    mov ebx, 2
    idiv ebx ; eax = edx:eax / ebx = x / 2
    mov ebx, eax ; save the result in ebx so we can do the other operations
    mov al, [b]
    cbw ; ax = b
    add ax, [a] ; ax = a + b
    mov dx, 100
    imul dx ; dx:ax = ax * dx = 100 * (a + b)
    push dx
    push ax
    pop eax ; 100 * (a + b)
    add ebx, eax ; ebx = x / 2 + 100 * (a + b)
    mov al, [d] ; al = d
    cbw ; ax = d
    add ax, word [c] ; ax = c + d
    mov cx, ax ; cx = c + d
    mov ax, 3
    cwd
    idiv cx ; ax = dx:ax / cx 
    cwd
    push dx
    push ax
    pop eax ; eax = 3 / (c + d)
    sub ebx, eax
    mov eax, ebx
    cdq ; edx:eax = x / 2 + 100 * (a + b) - 3 / (c + d)
    mov ebx, eax
    mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
    mov eax, [e]
    imul dword [e] ; edx:eax = e * e
    add eax, ebx
    adc edx, ecx
    mov dword [result + 0], eax 
    mov dword [result + 4], edx

tôi đã làm cho nó phức tạp một cách không cần thiết?

Trả lời

6 SepRoland Oct 22 2020 at 03:52

viết thuật toán cho: x / 2 + 100 * (a + b) - 3 / (c + d) + e * e

a, c - word,
b, d - byte,
e - doubleword,
x - qword

Vì số lớn nhất của bạn là 64 bit ( x là một từ khóa), nên kết quả cuối cùng của bạn cũng sẽ phải là 64 bit!

Thao tác đầu tiên của bạn là chia qword trong x cho 2. Bạn có vẻ mong đợi rằng kết quả này sẽ vừa với một từ khóa duy nhất vì bạn đã di chuyển thương số trong thanh EBXghi. Bạn không thể đưa ra giả định này và tệ hơn là phép chia có thể dễ dàng tạo ra ngoại lệ chia nếu thương số không vừa với 32 bit.
Đối với giải pháp, bạn nên biết rằng chia cho 2 thực ra chỉ đơn giản là một sự dịch chuyển sang phải.

mov   ebx, [x]
mov   ebp, [x + 4] ; EBP:EBX is x
sar   ebp, 1
rcr   ebx, 1       ; EBP:EBX is x / 2

Điều này có nghĩa là bạn cũng sẽ phải mở rộng quy mô các phép tính khác để thêm chúng vào EBP:EBXsử dụng:

add   ebx, ...
adc   ebp, ...

Vì phép cộng có tính chất liên kết, bạn có thể bắt đầu bằng cách tính phần e * e . Bạn đã không sắp xếp lại biểu thức và cuối cùng phải di chuyển xung quanh một số thanh ghi nữa. Không phải là một vấn đề lớn, nhưng tốt hơn theo cách của tôi:

mov   eax, [e]
imul  eax
add   ebx, eax
adc   ebp, edx

Sau đó đến 100 * (a + b) :

movsx eax, word [a]
movsx edx, byte [b]
add   eax, edx       ; eax = a + b
mov   edx, 100
imul  edx            ; edx:eax = 100 * (a + b)
add   ebx, eax
adc   ebp, edx

Tôi sẽ để lại 3 / (c + d) cho bạn ...

... và cuối cùng kết thúc sẽ là:

sub   ebx, eax
sbb   ebp, edx
mov   [result + 0], ebx 
mov   [result + 4], ebp

tôi đã làm cho nó phức tạp một cách không cần thiết?

  • Hơi khó đọc chương trình của bạn vì bạn không chèn một số dòng trống giữa các thao tác khác nhau.

  • Bạn không cần phải viết thẻ kích thước (byte, từ, mật mã) nếu thanh ghi liên quan đã ngụ ý kích thước. Trong mov dword [result + 0], eaxthẻ dword là thừa.

  • Tốt nhất là các bình luận trong chương trình được căn chỉnh phía trên nhau.

  • Đọc lại cẩn thận để tránh lỗi chính tả như trong:

      mov ecx, edx ; ecx:edx = x / 2 + 100 * (a + b) - 3 / (c + d)
    

    Nên ECX:EBX.

  • Để tính bình phương: khi bạn đã tải số vào thanh ghi, bạn có thể nhân với cùng thanh ghi đó và không phải chuyển sang bộ nhớ lần thứ hai như bạn đã làm:

      mov   eax, [e]
      imul  eax        ; Don't write "imul dword [e]"