x / 2 + 100 * (a + b)-3 / (c + d) + e * e in assembly

Oct 21 2020

알고리즘 작성 : x / 2 + 100 * (a + b)-3 / (c + d) + e * e 알고있는 것 : 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

불필요하게 복잡하게 만들었나요?

답변

6 SepRoland Oct 22 2020 at 03:52

다음에 대한 알고리즘 작성 : x / 2 + 100 * (a + b)-3 / (c + d) + e * e

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

가장 큰 숫자는 64 비트 ( x 는 qword)이므로 최종 결과도 64 비트 여야합니다!

첫 번째 작업은 x 의 qword를 2 로 나누는 것이 었습니다 EBX. 레지스터 에서 몫을 이동했기 때문에이 결과가 단일 dword에 맞을 것으로 예상하는 것 같습니다 . 이 가정을 할 수 없으며 몫이 32 비트에 맞지 않으면 나누기가 쉽게 나누기 예외를 생성 할 수 있습니다.
솔루션의 경우 2로 나누는 것은 실제로 단순히 오른쪽으로 이동하는 것입니다.

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

즉, 다음을 EBP:EBX사용하여 추가하려면 다른 계산도 확장해야합니다 .

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

덧셈은 연관 적이기 때문에 e * e 부분 을 계산하여 시작할 수 있습니다 . 식을 재 배열하지 않았고 결국 레지스터를 좀 더 이동해야했습니다. 큰 문제는 아니지만 내 방식이 더 좋습니다.

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

그런 다음 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

나는 3 / (c + d) 를 당신에게 남겨 둘 것입니다 ...

... 그리고 마지막으로 끝은 :

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

불필요하게 복잡하게 만들었나요?

  • 다른 작업 사이에 빈 줄을 삽입하지 않았기 때문에 프로그램을 읽는 것이 약간 어려웠습니다.

  • 관련된 레지스터가 이미 크기를 의미하는 경우 크기 태그 (바이트, 워드, dword)를 작성할 필요가 없습니다. 년 mov dword [result + 0], eax에 DWORD 태그 중복됩니다.

  • 프로그램의 주석을 서로 위에 정렬하는 것이 가장 좋습니다.

  • 다음과 같은 오타를 피하기 위해주의 깊게 다시 읽으십시오.

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

    이어야 ECX:EBX합니다.

  • 제곱을 계산하려면 : 레지스터에 숫자를로드 한 후 동일한 레지스터를 곱하고 두 번째로 메모리를 사용하지 않아도됩니다.

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