【发布时间】:2018-11-26 03:20:54
【问题描述】:
总结:我们在 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
【问题讨论】:
-
不会帮助您将代码拆分到 BSS 和文本部分。使用 POP 从传递给函数的堆栈中获取参数是非常混乱的。你也没有考虑到当一个函数被调用时,栈顶的东西就是返回地址。
-
@MichaelPetch 感谢您的意见。正如我所说,我们对实际的汇编编程是全新的,所以会发生这类重大错误。现在有什么新的意见吗?
-
此时@Jester 会建议使用调试器(如
gdb)来单步执行指令并查看内存/寄存器和执行的指令以查看失败的地方。 -
如果您想发布代码的工作版本,请将其发布为答案。修复问题中的错误会使答案无效。我回滚了你的编辑。
标签: c arrays gcc assembly nasm