x / 2 + 100 * (a + b)-3 / (c + d) + e * e in assembly
알고리즘 작성 : 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
불필요하게 복잡하게 만들었나요?
답변
다음에 대한 알고리즘 작성 : 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]"