x64 位程序集 [英] x64 bit assembly

查看:29
本文介绍了x64 位程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

main.c:

#include extern void printnum(int i);int main(void){打印编号(8);打印编号(256);返回0;}

32 位版本:

<代码>;main.c:http://pastebin.com/f6wEvwTq;nasm -f elf32 -o printnum.o printnum.asm;gcc -o printnum printnum.o main.c -m32.data 节_nl db 0x0AnlLen 等于 $ - _nl节.text全球印刷号码打印编号:输入 0,0mov eax, [ebp+8]异或 ebx, ebx异或 ecx, ecx异或edx, edx推 ebxmov ebx, 10开始循环:Idiv ebx添加edx,0x30推 dx ;对于奇数位数,这会搞砸堆栈,但没关系;因为无论如何我们都会在这个函数的末尾重置堆栈.;虽然需要修复.公司异或edx, edxcmp eax, 0jne 开始循环推ECXimul ecx, 2mov edx, ecx移动 eax, 4 ;将字符串(从堆栈中)打印到屏幕mov ebx, 1mov ecx, esp添加 ecx, 4整数 80 小时移动 eax, 4 ;打印一个新行mov ebx, 1mov ecx, _nlmov edx, nlLen整数 80 小时流行音乐;返回已使用字符的数量离开退

x64 版本:

<代码>;main.c:http://pastebin.com/f6wEvwTq;nasm -f elf64 -o 对象/printnum.o printnum.asm;gcc -o bin/printnum object/printnum.o main.c -m64.data 节_nl db 0x0AnlLen 等于 $ - _nl节.text全球印刷号码打印编号:输入 0, 0mov rax, [rbp + 8] ;从 stac 获取函数 args异或 rbx, rbx异或 rcx, rcx异或 rdx, rdx推 rbx ;字符串的 0 字节移动 rbx, 10 ;分频器开始循环:idiv rbx ;模在 rdx 中添加 rdx, 0x30推dx包括 rcx ;增加循环变量异或 rdx, rdx ;重置模数cmp rax, 0jne 开始循环推 rcx ;将计数器压入堆栈imul rcx, 2移动 rdx, rcx ;字符串长度mov rax, 4移动 rbx, 1mov rcx, rsp ;字符串添加 rcx, 4整数 0x80mov rax, 4移动 rbx, 1mov rcx, _nlmov rdx, nlLen整数 0x80流行音乐离开退;返回到 C 例程

提前致谢!

解决方案

我不确定这个答案是否与您看到的问题有关(因为您没有指定任何有关失败的内容),但是64 位代码与 32 位代码具有不同的调用约定.两个主要的 64 位 Intel ABI(Windows 和 Linux/BSD/Mac OS)都在寄存器中而不是在堆栈中传递函数参数.您的程序似乎仍在堆栈中等待它们,这不是正常的处理方式.

现在我看到有一个 C main() 例程调用您的函数,我的回答是正是关于您遇到的问题.>

I started assembly (nasm) programming not too long ago. Now I made a C function with assembly implementation which prints an integer. I got it working using the extended registers, but when I want to write it with the x64 registers (rax, rbx, ..) my implementation fails. Does any of you see what I missed?

main.c:

#include <stdio.h>

extern void printnum(int i);

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

        return 0;
}

32 bit version:

; 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 version:

; 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

Thanks in advance!

解决方案

I'm not sure if this answer is related to the problem you're seeing (since you didn't specify anything about what the failure is), but 64-bit code has a different calling convention than 32-bit code does. Both of the major 64-bit Intel ABIs (Windows & Linux/BSD/Mac OS) pass function parameters in registers and not on the stack. Your program appears to still be expecting them on the stack, which isn't the normal way to go about it.

Edit: Now that I see there is a C main() routine that calls your functions, my answer is exactly about the problem you're having.

这篇关于x64 位程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆