我有一个任务来编写可从C读取并声明如下的汇编例程:
extern int solve_equation(long int a, long int b,long int c, long int *x, long int *y);
找到方程式的解决方案
a * x + b * y = c
在-2147483648 <x, y <2147483647
中,选中所有选项。
如果找到解决方案,则例程返回的值将为1
,而另一个0
将会返回。
您必须考虑到以下计算结果:a * x, b * y, a * x + b * y
可能超过32位。
.MODEL SMALL
.DATA
C DQ ?
SUM DQ 0
MUL1 DQ ?
MUL2 DQ ?
X DD ?
Y DD ?
.CODE
.386
PUBLIC _solve_equation
_solve_equation PROC NEAR
PUSH BP
MOV BP,SP
PUSH SI
MOV X,-2147483648
MOV Y,-2147483648
MOV ECX,4294967295
FOR1:
CMP ECX,0
JE FALSE
PUSH ECX
MOV Y,-2147483648
MOV ECX,4294967295
FOR2:
MOV SUM,0
CMP ECX,0
JE SET_FOR1
MOV EAX,DWORD PTR [BP+4]
IMUL X
MOV DWORD PTR MUL1,EAX
MOV DWORD PTR MUL1+4,EDX
MOV EAX,DWORD PTR [BP+8]
IMUL Y
MOV DWORD PTR MUL2,EAX
MOV DWORD PTR MUL2+4,EDX
MOV EAX, DWORD PTR MUL1
ADD DWORD PTR SUM,EAX
MOV EAX, DWORD PTR MUL2
ADD DWORD PTR SUM,EAX
MOV EAX, DWORD PTR MUL1+4
ADD DWORD PTR SUM+4,EAX
MOV EAX, DWORD PTR MUL2+4
ADD DWORD PTR SUM+4,EAX
CMP SUM,-2147483648
JL SET_FOR2
CMP SUM,2147483647
JG SET_FOR2
MOV EAX,DWORD PTR [BP+12]
CMP DWORD PTR SUM,EAX
JE TRUE
SET_FOR2:
DEC ECX
INC Y
JMP FOR2
SET_FOR1:
POP ECX
DEC ECX
JMP FOR1
FALSE:
MOV AX,0
JMP SOF
TRUE:
MOV SI,WORD PTR [BP+16]
MOV EAX,X
MOV DWORD PTR [SI],EAX
MOV SI,WORD PTR [BP+18]
MOV EAX,Y
MOV DWORD PTR [SI],EAX
MOV AX,1
SOF:
POP SI
POP BP
RET
_solve_equation ENDP
END
这是处理大量数字的正确方法吗?
尝试执行操作时,我得到操作或指令has illegal size
的参数:
MOV SUM,0
CMP SUM,-2147483648
CMP SUM,2147483647
主要代码:
int main()
{
long int x, y, flag;
flag = solve_equation(-5,4,2147483647,&x, &y);
if (flag == 1)
printf("%ld*%ld + %ld*%ld = %ld\n", -5L,x,4L,y,2147483647);
return 0;
}
输出
-5*-2147483647 + 4*-2147483647 = 2147483647
我使用dosbox 0.74和tcc
答案 0 :(得分:3)
您使用的是16位代码,因此64位操作数大小不可用。您的汇编器神奇地将大小与sum
关联,因为您已将sum dq 0
定义为大小。
因此mov sum, 0
等效于mov qword ptr [sum], 0
,它当然不会以16位或32位模式进行汇编;您只能使用整数运算一次最多处理32位。
(32位操作数大小在386兼容CPU上以16位模式可用,使用的机器编码与在32位模式下允许16位操作数大小的机器编码相同。但是64位操作数大小仅可用在64位模式下运行。与386不同,AMD64出于各种原因未向以前存在的模式添加任何新的前缀或任何内容。)
您可以通过SSE存储将整个64位sum
归零,甚至可以与SSE4.2 pcmpgtq
进行比较,但这可能不是您想要的。
您似乎想检查64位sum
是否适合32位。 (即,如果它是符号扩展的32位整数)。
所以实际上,您只需要检查所有32个高位是否相同并匹配低半部分的第31位即可。
mov eax, dword ptr [sum]
cdq ; sign extend eax into edx:eax
; i.e. copy bit 31 of EAX to all bits of EDX
cmp edx, dword ptr [sum+4]
je small_sum