在 C 中调用汇编函数,反转字符串

标签 c arrays assembly cpu-registers

我正在尝试编写一个 c 程序,它将调用一个汇编函数来反转一个字符串。但是,我很难让汇编代码遍历字符串以找到结束字符“0”。

我的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”后立即失败。

在使用“display/c $edi”显示 edi 寄存器时使用 GDB 在第 25 行中断运行产生以下输出:

(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 寄存器时是否做错了什么?

最佳答案

您将 edi 寄存器的内容打印为一个字符,但内容实际上是一个地址。您真正想要的是显示 edi 中的地址指向什么。

也许试试

display *((char *) $edi)

关于在 C 中调用汇编函数,反转字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16398208/

相关文章:

c - strcmp 何时不返回 -1、0 或 1?

arrays - C 具有可变大小的初始化和未初始化数组

algorithm - 如何在汇编中将两个十六进制 128 位数字相乘

c - __VA_ARGS__ 扩展使用 MSVC

c - 结构体中字符串的初始化

javascript - 关于递增反 Angular js,递减计数器未按预期工作

java - 找到多维数组中最大的元素

c++ - 为什么结构数组不需要成员运算符?

c - 零初始化结构未出现在内存中

assembly - 使用手写汇编调用 native 代码