使用 nasm x86-64 将实现放入汇编中
puts implementation in assembly with nasm x86-64
我是汇编的新手,我正在尝试在我的 Ubuntu.
上使用 nasm x86-64 进行汇编的 C 函数的实现
在我为函数编写测试之前一切都很好:有一个我无法重现的行为:
当我发送 char *str = strdup("");对于我的 puts 函数(别名 ft_puts),我的函数 return 出现错误,而不是像原始 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标签哈哈,这么多问题)
两个问题。第一,允许 call strlen
破坏一些寄存器,其中包括 rdi
,您稍后需要它。所以,用 push rdi
和 pop rdi
包围 call strlen
来保存和恢复它。
其次,您没有在 print_newline
块中初始化 rdi
。您需要将它设置为 1
for stdout
就像您在 print_string
块中所做的那样。
PS: 你应该学会使用调试器。
我是汇编的新手,我正在尝试在我的 Ubuntu.
上使用 nasm x86-64 进行汇编的 C 函数的实现在我为函数编写测试之前一切都很好:有一个我无法重现的行为: 当我发送 char *str = strdup("");对于我的 puts 函数(别名 ft_puts),我的函数 return 出现错误,而不是像原始 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标签哈哈,这么多问题)
两个问题。第一,允许 call strlen
破坏一些寄存器,其中包括 rdi
,您稍后需要它。所以,用 push rdi
和 pop rdi
包围 call strlen
来保存和恢复它。
其次,您没有在 print_newline
块中初始化 rdi
。您需要将它设置为 1
for stdout
就像您在 print_string
块中所做的那样。
PS: 你应该学会使用调试器。