我正在大学课程中学习IA32位汇编,我很难回复64位数字。我必须做(var8 + var16) - (var32 + var32x),并以64位int显示结果。我得到了正确的结果,但数字应为负数。你能看一下这个并给我一些关于我做错什么的见解吗?
谢谢
继承我的代码:
function.h:
long function(void);
function.s:
.section .data
.global var8
.global var16
.global var32
.global varx32
.global res
.section .text
.global function
function:
movl $0, %eax
movl $0, %edx
movl var32, %eax
movl varx32, %edx
addl %edx, %eax
movl $0, %ebx
movw var16, %bx
movl $0, %ecx
movb var8, %cl
addl %ebx, %ecx
sbb %ecx, %eax
movl %eax, res
ret
的main.c
#include <stdio.h>
#include "function.h"
char var8= 127;
short var16=32767;
int var32=2147483647, varx32=2147483647;
long long res=0;
int main(void) {
printf("Value A: %d\nValue B: %d\nValue C: %d\nValue D: %d\n", var8, var16, var32, varx32);
function();
printf("\n%lld\n", res);
return 0;
}
答案 0 :(得分:0)
不要忘记符号位。现在你只能用正数来计算。如果使用负值处理,则术语的结果可能会溢出32位寄存器。因此,将此结果存储在两个32位寄存器中。
res
是一个64位变量(long long),即8个字节。您将%eax
存储到res
- 只有4个字节。高4个字节保持为空(long long res=0;
)。因此结果将始终为正,因为符号位(最高字节的最高位)为空。
TL; DR - 尝试理解以下功能:
function:
pushl %ebx # to be preserved by the callee (https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl)
movswl var16, %eax # = `movsx eax, var16` (https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html)
movsbl var8, %edx # = `movsx edx, var8` (https://sourceware.org/binutils/docs/as/i386_002dMnemonics.html)
addl %edx, %eax
movl $0, %edx
adcl $0, %edx # EDX:EAX Result of first term
movl var32, %ebx
addl varx32, %ebx
movl $0, %ecx
adcl $0, %ecx # ECX:EBX Result of second term
subl %ebx, %eax # EDX:EAX = EDX:EAX - ECX:EBX
sbbl %ecx, %edx
movl %eax, res # Store EDX:EAX to `res`
movl %edx, res + 4
popl %ebx # return EBX unchanged
ret
我改变了计算顺序和使用过的寄存器。按照惯例,函数的返回值存储在EAX
(32位)或EDX:EAX
(64位)中。如果您决定将function
的返回类型从long
(32位环境中的32位)更改为long long
(64位),那么您还可以使用我的返回值功能