修改外部汇编程序

时间:2018-06-16 16:46:00

标签: c arrays gcc assembly nasm

摘要:我们在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

2 个答案:

答案 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