摘要:我们在C中有一个int变量和4个双数组,其中2个包含输入数据,其中2个我们要写输出数据。我们将变量和数组传递给外部.asm文件中的函数,其中输入数据用于确定输出数据,输出数据被写入输出数组。
我们的问题是,在汇编例程完成其工作后,输出数组看起来仍未受影响。如果例程读取正确的输入数据,我们甚至不知道。我们哪里出错?
我们使用以下命令编译
nasm -f elf32 -o calculation.o calculation.asm
gcc -m32 -o programm main.c calculation.o
如果您需要更多信息,请随时提出。
C代码:
// before int main()
extern void calculate(int32_t counter, double radius[], double distance[], double paper[], double china[]) asm("calculate");
// in int main()
double radius[counter];
double distance[counter];
// [..] Write Input Data to radius & distance [...]
double paper[counter];
double china[counter];
for(int i = 0; i < counter; i++) {
paper[i] = 0;
china[i] = 0;
}
calculate(counter, radius, distance, paper, china);
// here we expect paper[] and china[] to contain output data
我们的汇编代码目前只接受值,将它们放入FPU,然后将它们放入输出数组中。
x86汇编(英特尔语法)(我知道,这段代码看起来很糟糕,但我们是初学者,所以请耐心等待;另外,我不能让语法高亮显示正常工作):BITS 32
GLOBAL calculate
calculate:
SECTION .BSS
; declare all variables
pRadius: DD 0
pDistance: DD 0
pPaper: DD 0
pChina: DD 0
numItems: DD 0
counter: DD 0
; populate them
POP DWORD [numItems]
POP DWORD [pRadius]
POP DWORD [pDistance]
POP DWORD [pPaper]
POP DWORD [pChina]
SECTION .TEXT
PUSH EBX ; because of cdecl calling convention
JMP calcLoopCond
calcLoop:
; get input array element
MOV EBX, [counter]
MOV EAX, [pDistance]
; move it into fpu, then move it to output
FLD QWORD [EAX + EBX * 8]
MOV EAX, [pPaper]
FSTP QWORD [EAX + EBX * 8]
; same for the second one
MOV EAX, [pRadius]
FLD QWORD [EAX + EBX * 8]
MOV EAX, [pChina]
FSTP QWORD [EAX + EBX * 8]
INC EBX
MOV [counter], EBX
calcLoopCond:
MOV EAX, [counter]
MOV EBX, [numItems]
CMP EAX, EBX
JNZ calcLoop
POP EBX
RET
答案 0 :(得分:2)
汇编程序例程中存在一些问题。 POP
指令会发送到.bss
部分,因此永远不会执行。在POP
s的序列中,不考虑返回地址(由调用者推送)。根据ABI,您必须将参数保留在堆栈中。因为永远不会执行POP
,所以循环退出条件总是正确。
你真的不应该这样使用全局变量。相反,创建一个堆栈框架并使用它。
答案 1 :(得分:0)
感谢您的所有答案和评论以及一些繁重的研究,我们设法最终生成了正常运行的代码,现在正确使用堆栈框架并完成cdecl调用约定:
BITS 32
GLOBAL calculate
SECTION .DATA
electricFieldConstant DQ 8.85e-12
permittivityPaper DQ 3.7
permittivityChina DQ 7.0
SECTION .TEXT
calculate:
PUSH EBP
MOV EBP, ESP
PUSH EBX
PUSH ESI
PUSH EDI
MOV ECX, 0 ; counter for loop
JMP calcLoopCond
calcLoop:
MOV EAX, [EBP + 12]
FLD QWORD [EAX + ECX * 8]
MOV EAX, [EBP + 20]
FSTP QWORD [EAX + ECX * 8]
MOV EAX, [EBP + 16]
FLD QWORD [EAX + ECX * 8]
MOV EAX, [EBP + 24]
FSTP QWORD [EAX + ECX * 8]
ADD ECX, 1 ; increase loop counter
calcLoopCond:
MOV EDX, [EBP + 8]
CMP ECX, EDX
JNZ calcLoop
POP EDI
POP ESI
POP EBX
MOV ESP, EBP
POP EBP
RET