gpt4 book ai didi

linux - x64 位汇编

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:25:25 25 4
gpt4 key购买 nike

我不久前开始汇编 (nasm) 编程。现在我创建了一个带有汇编实现的 C 函数,它打印一个整数。我使用扩展寄存器让它工作,但是当我想用 x64 寄存器(rax、rbx、..)编写它时,我的实现失败了。你们有人看到我错过了什么吗?

主.c:

#include <stdio.h>

extern void printnum(int i);

int main(void)
{
printnum(8);
printnum(256);

return 0;
}

32 位版本:

; main.c: http://pastebin.com/f6wEvwTq
; nasm -f elf32 -o printnum.o printnum.asm
; gcc -o printnum printnum.o main.c -m32

section .data
_nl db 0x0A
nlLen equ $ - _nl

section .text
global printnum


printnum:
enter 0,0

mov eax, [ebp+8]

xor ebx, ebx
xor ecx, ecx
xor edx, edx
push ebx
mov ebx, 10

startLoop:

idiv ebx
add edx, 0x30

push dx ; With an odd number of digits this will screw up the stack, but that's ok
; because we'll reset the stack at the end of this function anyway.
; Needs fixing though.
inc ecx
xor edx, edx

cmp eax, 0
jne startLoop

push ecx
imul ecx, 2

mov edx, ecx

mov eax, 4 ; Prints the string (from stack) to screen
mov ebx, 1
mov ecx, esp
add ecx, 4
int 80h

mov eax, 4 ; Prints a new line
mov ebx, 1
mov ecx, _nl
mov edx, nlLen
int 80h

pop eax ; returns the ammount of used characters

leave
ret

x64 版本:

; main.c : http://pastebin.com/f6wEvwTq
; nasm -f elf64 -o object/printnum.o printnum.asm
; gcc -o bin/printnum object/printnum.o main.c -m64

section .data
_nl db 0x0A
nlLen equ $ - _nl

section .text
global printnum

printnum:
enter 0, 0

mov rax, [rbp + 8] ; Get the function args from the stac
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx

push rbx ; The 0 byte of the string
mov rbx, 10 ; Dividor

startLoop:
idiv rbx ; modulo is in rdx
add rdx, 0x30

push dx

inc rcx ; increase the loop variable
xor rdx, rdx ; resetting the modulo

cmp rax, 0
jne startLoop

push rcx ; push the counter on the stack
imul rcx, 2

mov rdx, rcx ; string length

mov rax, 4
mov rbx, 1
mov rcx, rsp ; the string
add rcx, 4
int 0x80

mov rax, 4
mov rbx, 1
mov rcx, _nl
mov rdx, nlLen
int 0x80

pop rax
leave

ret ; return to the C routine

提前致谢!

最佳答案

我认为您的问题是您试图在 64 位模式下使用 32 位调用约定。如果您从 C 调用这些汇编例程,那是行不通的。此处记录了 64 位调用约定:http://www.x86-64.org/documentation/abi.pdf

另外,不要打开代码系统调用。调用 C 库中的包装器。这样 errno 就可以正确设置,你可以利用 sysenter/syscall,你不必处理正常调用之间的差异约定和系统调用参数约定,并且您可以避免某些低级 ABI 问题。 (您的另一个问题是 write 是 Linux/x86-64 的系统调用编号 1,而不是 4。)

除编辑外:如今在汇编中编写任何东西有两个,而且只有两个原因:

  1. 您正在编写为数不多的不能单独用 C 编写的深层魔法(一个很好的例子是 libffi 的内容)
  2. 您正在手动优化一个内部循环子例程,该子例程被测量为性能关键型,而 C 编译器在这方面做得不够好。

否则就用 C 写任何东西。你的继任者会感谢你的。

编辑:检查系统调用号码。

关于linux - x64 位汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5022744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com