【问题标题】:puts implementation in assembly with nasm x86-64使用 nasm x86-64 在汇编中实现
【发布时间】:2015-06-09 23:21:09
【问题描述】:

我是汇编新手,我正在尝试在我的 Ubuntu 上使用 nasm x86-64 实现 C 函数的实现。

在我为函数编写测试之前一切都很好:有一种我无法重现的行为: 当我发送 char *str = strdup("");对于我的 puts 函数(别名 ft_puts),我的函数返回一个错误,而不是像原始 puts 函数那样打印换行符。

这是我的 puts 实现 (ft_puts.s):

section .data
new_line        db      10      ; new line

section     .text
global      ft_puts
extern      strlen

ft_puts:                        ; Alias int puts(const char *s)
    call    strlen
    push    rax                 ; Number of printed chars have to be returned by ft_puts

    cmp     rax, 0
    jg      print_string        ; if length > 0, print string
    cmp     rax, 0
    jz      print_newline       ; else if length == 0 (jle or <= 0, give the same result to my problem), print new line char
    jmp     error               ; else go to error

print_string:
    mov     rsi, rdi            ; string arg for write
    mov     rdi, 1              ; file_descriptor arg for write
    mov     rdx, rax            ; length arg returned by ft_strlen for write
    mov     rax, 1              ; write
    syscall

    test    rax, rax
    jle     error               ; if write failed, go to error
    jmp     print_newline       ; else print new line char

print_newline:
    mov     rsi, new_line       ; new line as string arg for write
    mov     rdx, 1              ; new line string length
    mov     rax, 1              ; write
    syscall

    test    rax, rax
    jle     error               ; if write failed, go to error
    jmp     success             ; else go to success

success:
    pop     rax                 ; Get number of chars printed by print_string
    inc     rax                 ; Add new line printed by print_newline to this number
    jmp     end

error:
    pop     rax
    mov     rax, -1             ; Return EOF (alias -1) on error
    jmp     end

end:
    ret

抱歉,如果我的代码看起来很糟糕,我是在一周前开始组装的。 我是 Stack Overflow 的新手,帮助中心告诉我提供代码来测试我的代码。所以,这是一个 main.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int ft_puts(const char *s);

int main(void)
{
    char    *str;
    int     ret[2];

    str = strdup(".");

    write(1, "[", 1);
    ret[0] = puts(str);
    write(1, "]", 1);
    write(1, "\n", 1);
    write(1, "[", 1);
    ret[1] = ft_puts(str);
    write(1, "]\n", 2);

    printf("puts return value : %d | ft_puts return value : %d\n\n", ret[0], ret[1]);
    free(str);


    str = strdup("");

    write(1, "[", 1);
    ret[0] = puts(str);
    write(1, "]", 1);
    write(1, "\n", 1);
    write(1, "[", 1);
    ret[1] = ft_puts(str);
    write(1, "]\n", 2);

    printf("puts return value : %d | ft_puts return value : %d\n", ret[0], ret[1]);
    free(str);

    return (0);
}

并编译和运行这段代码:)

nasm -f elf64 ft_puts.s -o ft_puts.o
gcc -c main.c
gcc main.o ft_puts.o -o test
./test

问题似乎出在我的 print_newline 标签中,但我找不到。如果有人可以帮助我? (在我身边很难获得关于汇编语言的帮助) (我不知道是否应该在我的问题中包含C标签哈哈,这么多问题)

【问题讨论】:

    标签: assembly nasm x86-64 puts


    【解决方案1】:

    两个问题。一,call strlen 被允许破坏一些包括rdi 的寄存器,你以后需要它。所以,用push rdipop rdi包围call strlen来保存和恢复它。

    其次,您没有在print_newline 块中初始化rdi。您需要像在 print_string 块中所做的那样,将 stdout 设置为 1

    PS:你应该学会使用调试器。

    【讨论】:

    • 感谢您的建议 :) print_newline 块中 rdi 的初始化确实解决了我的问题。 (我有一天会尝试调试器)
    • 在没有调试器的情况下用 asm 编程有点像在没有后视镜的情况下驾驶汽车。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 2017-12-26
    • 2022-10-15
    • 1970-01-01
    • 2017-01-13
    • 2014-02-22
    • 2012-06-08
    相关资源
    最近更新 更多