我正在尝试编写一个将调用汇编函数来反转字符串的c程序。但是,我很难获取汇编代码来遍历字符串来查找结尾字符“0”。在C中调用汇编函数,反转字符串
我的C代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// These functions will be implemented in assembly:
//
void strrev(char *str) ;
int main(){
char *str1;
str1 = strdup("Hello World");
strrev(str1);
printf("str1 reversed: \"%s\"\n", str1) ;
free(str1);
return 0;
}
任何我的汇编代码很简单:
; File: strrev.asm
; A subroutine called from C programs.
; Parameters: string A
; Result: String is reversed and returned.
SECTION .text
global strrev
_strrev: nop
strrev:
push ebp
mov ebp, esp
; registers ebx,esi, and edi must be saved if used
push ebx
push edi
xor esi, esi
xor eax, eax
lea ecx, [esp+8] ; load the start of the array into ecx
jecxz end ; jump if [ecx] is zero
mov edi, ecx
reverseLoop:
cmp byte[edi], 0
je end
inc edi
inc eax
jmp reverseLoop
end:
pop edi ; restore registers
pop ebx
mov esp, ebp ; take down stack frame
pop ebp
ret
所有我想这个代码,现在所要做的只是通过串迭代,直到它找到在reverseLoop内部结束。但是,如果我尝试使用gdb并逐步执行程序,则在查看第一个字符“H”后,它似乎立即失败。
运行与GDB与线25断裂,同时显示与“显示/ C $ EDI”的EDI寄存器产生以下输出:
(gdb)
reverseLoop() at strrev.asm:25
25 cmp byte[edi], 0
1: /c $edi = 72 'H'
哪个是正确的,但如果我通过下台到INC edi,edi立即变得不正确。它应该是“E”,因为“Hello World”中的第二个字符是“e”。但是,gdb的输出列出其为“I”:
27 inc edi
1: /c $edi = 72 'H'
(gdb)
28 inc eax
1: /c $edi = 73 'I'
难道我做错了什么,当我通过EDI注册迭代?
顺便说一句,这是一个32位或64位系统上?如果它是一个64位系统,则删除地址的前32位,使指针指向内存中完全不同的地方。 – 2013-05-06 12:14:25
第一个参数是[ebp + 8] NOT [esp + 8]。你也应该使用LEA的MOV instea,否则''((char *)$ ebp + 8)'而不是'(*(char **)($ ebp + 8))''。看看我的回答 – scottt 2013-05-06 12:36:58