繁体   English   中英

在外部汇编程序中修改C数组

[英]Modify C array in external assembler routine

摘要:我们在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 Assembly(Intel语法)(我知道,这段代码看起来很恐怖,但是我们是初学者,所以请多多包涵;另外,我也无法突出显示语法来对此代码正确工作):

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

汇编程序中有两个问题。 POP指令发送到.bss节中,因此它们从不执行。 POP序列中,不考虑返回地址(由调用方推送)。 根据ABI,无论如何,您必须将参数保留在堆栈上。 因为从不执行POP ,所以循环退出条件总是碰巧为true。

而且,您实际上不应该以这种方式使用全局变量。 而是创建一个堆栈框架并使用它。

感谢您的所有答复和评论以及大量研究工作,我们终于成功产生了可运行的代码,该代码现在可以正确使用堆栈框架并满足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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM