标签: x86-64

x86_64 Linux 系统的 GCC 调用约定

我编写了一个最小函数来测试是否可以调用/链接 C 和 x86_64 汇编代码。

这是我的main.c

#include <stdio.h>

extern int test(int);

int main(int argc, char* argv[])
{

    int a = 10;
    
    int b = test(a);

    printf("b=%d\n", b);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是我的test.asm

section .text
    global test

test:
    mov ebx,2
    add eax,ebx
    ret
Run Code Online (Sandbox Code Playgroud)

我使用这个脚本构建了一个可执行文件

#!/usr/bin/env bash

nasm -f elf64 test.asm -o test.o

gcc -c main.c -o main.o

gcc main.o test.o -o a.out
Run Code Online (Sandbox Code Playgroud)

我写的时候test.asm并没有任何真正的线索我在做什么。然后我离开并做了一些阅读,现在我不明白我的代码是如何工作的,因为我说服自己它不应该这样。

以下是我认为这不起作用的原因列表:

  • 我不保存或恢复基指针(设置堆栈帧)。我实际上不明白为什么需要这样做,但我看过的每个例子都是这样做的。
  • Linux 系统上 gcc 编译器的调用约定应该是通过堆栈传递参数。这里我假设参数是使用eaxand传递的ebx。我认为这是不对的。
  • ret可能希望从某个地方获取返回地址。我相当确定我没有提供这个。
  • 甚至可能还有其他我不知道的原因。

我所编写的内容产生正确的输出完全是侥幸吗?

我对此完全陌生。虽然我顺便听说过一些 …

c linux gcc x86-64 calling-convention

0
推荐指数
1
解决办法
1196
查看次数

汇编中函数之间的参数传递如何进行?

所以我试图了解汇编编程如何与堆栈框架等一起工作。
我做了一些练习并使用 GDB 反汇编了一些 C 代码。现在的任务是找出“main”和函数之间的参数传输是如何工作的。我刚刚开始学习,有点迷失了下一个例子实际上在做什么。关于从哪里开始有什么想法或建议吗?

这是一个与教师合作的递归程序。

汇编代码如下所示:

    1149:   f3 0f 1e fa             endbr64 
    114d:   55                      push   rbp
    114e:   48 89 e5                mov    rbp,rsp
    1151:   48 83 ec 10             sub    rsp,0x10
    1155:   89 7d fc                mov    DWORD PTR [rbp-0x4],edi
    1158:   83 7d fc 01             cmp    DWORD PTR [rbp-0x4],0x1
    115c:   76 13                   jbe    1171 <f+0x28>
    115e:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
    1161:   83 e8 01                sub    eax,0x1
    1164:   89 c7                   mov    edi,eax
    1166:   e8 de ff ff ff          call …
Run Code Online (Sandbox Code Playgroud)

c recursion assembly x86-64 disassembly

0
推荐指数
1
解决办法
220
查看次数

了解汇编中的函数何时为 void 或 int

所以我在汇编中有以下代码:

在此输入图像描述

我知道该函数的参数有两个(x 和 y 或任何字母)。问题是我不知道如何从汇编代码中查看该函数是否返回任何内容,因为它只说ret. 这个函数会被视为 void 或 int 吗?任何有助于理解的解释将不胜感激。

assembly reverse-engineering x86-64 att

0
推荐指数
1
解决办法
622
查看次数

什么是 _IO_stdin_used

有人可以解释一下_IO_stdin_used下面这一行的内容吗:

114a:   48 8d 3d b3 0e 00 00    lea    rdi,[rip+0xeb3]        # 2004 <_IO_stdin_used+0x4>
Run Code Online (Sandbox Code Playgroud)

抱歉这个菜鸟问题。

c++ assembly printf reverse-engineering x86-64

0
推荐指数
1
解决办法
921
查看次数

如何从 Apple Silicon 中的 C 源代码创建 x86_64 汇编文件?

我当前的设置是 m1 MacBook Air。

\n

我正在阅读一本低级编程书籍。\n
\n我希望将我编写的 C 代码编译为 x86_64 程序集。

\n

有了 clang 我可以很容易地做到这一点:

\n
clang -target x86_64 -masm=intel -S add_two_numbers.c\n
Run Code Online (Sandbox Code Playgroud)\n

但当我包含一个库(例如 stdio)时它不起作用。

\n
\xe2\x9d\xaf clang -target x86_64 -masm=intel -S hello.c\nhello.c:1:10: fatal error: 'stdio.h' file not found\n#include <stdio.h>\n         ^~~~~~~~~\n
Run Code Online (Sandbox Code Playgroud)\n

正如 clang 文档所说,我可以手动安装 x86_64 库并执行以下操作:

\n
clang -target x86_64 -masm=intel -I path/to/Include -L path/to/Library -S hello.c\n
Run Code Online (Sandbox Code Playgroud)\n

但我找不到可在 MacOS 上下载的预构建包。我试过交叉编译,太费力了。

\n

所以我放弃了,转而追求更简单的东西。我找到了这个问题的解决方案,我将在下面作为答案分享。

\n

macos assembly x86-64 cross-compiling apple-silicon

0
推荐指数
1
解决办法
1075
查看次数

为每个 int8_t 元素添加两个具有饱和度的向量(uint64_t 类型)

我最近面临一个给定的问题:

\n
\n

向量中有8个元素,每个元素都用int8_t表示。

\n

在 x86_64 中实现一个算法,将两个向量(uint64_t 类型)相加。

\n

添加元素时应考虑饱和算术。

\n

例如:

\n

80 + 60 = 127

\n

(\xe2\x88\x9240) + (\xe2\x88\x92100) = \xe2\x88\x92128

\n
\n

最大的挑战是施加的限制:

\n
    \n
  • 除ret外无条件指令;没有跳跃、cmove、set 等。
  • \n
  • 该解不能长于 48 条指令(存在短于 37 条指令的解)
  • \n
\n

我想不出任何符合这些限制的解决方案。\n有人能给我一些提示吗?欢迎使用 C 语言的示例。

\n

我只能使用“标准”、传输、算术、逻辑指令和标准寄存器:

\n
    \n
  • mov cbw/cwde/cdqe cwd/cdq/cqo movzx movsx
  • \n
  • 添加 sub imul mul idiv div inc dec neg
  • \n
  • 和或异或非 sar sarx shr shrx shl shlx ror rol
  • \n
  • 雷雷
  • \n
\n

assembly bit-manipulation x86-64 saturation-arithmetic swar

0
推荐指数
1
解决办法
270
查看次数

为什么 Windows API WriteFile 要求将 rbx 设置为 [rsp]?

我正在尝试尝试在汇编中写入控制台。我最终使用了 Windows API WriteFile 函数。它运作良好,但我遇到了一个奇怪的怪癖。如果我没有将 rbx 寄存器设置为 [rsp],则 WriteFile 不会返回并给出错误代码 0xC0000005,这是访问冲突错误。它仍然可以正确写入控制台,我觉得这很奇怪。这不是问题,我可以包含一行,没问题。但这让我很困扰,因为我无法弄清楚为什么会出现这种行为。

如果它确实有帮助,我将使用 NASM 和 GCC 来编译我的程序。

这是上下文的完整代码:

bits 64
default rel

extern GetStdHandle
extern WriteFile
extern ExitProcess

section .data
buffer db 0

section .text

print:
    push    rbp
    mov     rbp, rsp
    add     rsp, 8

    mov     rcx, -11
    call    GetStdHandle
    mov     rcx, rax

    mov     rax, 0x61616161
    mov     [buffer], rax
    mov     rdx, buffer
    mov     r8, 4

    mov     rbx, [rsp]
    call    WriteFile

    mov     rsp, rbp
    pop     rbp

    ret


global main
main:
    call    print

    mov …
Run Code Online (Sandbox Code Playgroud)

windows assembly winapi x86-64 nasm

0
推荐指数
1
解决办法
96
查看次数

使用汇编除以 2 的可变幂

我有这个任务:

\n
\n
除幂2
\n

计算x /2 n,对于 0 \xe2\x89\xa4 n \xe2\x89\xa4 30。向零舍入。

\n
    \n
  • 论点1:x
  • \n
  • 论据2:n
  • \n
\n

例子:

\n
    \n
  • dividePower2(15,1) = 7
  • \n
  • dividePower2(-33,4) = -2
  • \n
\n
\n

这是我到目前为止所得到的,但我不知道我是否朝着正确的方向前进(需要 AT&T 语法):

\n
.global dividePower2\n   dividePower2:\n   sar $2, %esi\n   ret\n
Run Code Online (Sandbox Code Playgroud)\n

assembly bit-manipulation x86-64 bit-shift integer-division

0
推荐指数
1
解决办法
149
查看次数

为什么这段代码打印由 clang 和 gcc 编译的不同值?

汇编:

.intel_syntax noprefix
.global Foo
Foo:
    mov ax, 146
    ret
Run Code Online (Sandbox Code Playgroud)

主要.c:

#include <stdio.h>

extern int Foo(void);

int main(int argc, char** args){
    printf("Asm returned %d\n", Foo());
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在我编译并链接:

(compiler name) -c asm.s -o asm.o
(compiler name) asm.o main.c -o  main
./main
Run Code Online (Sandbox Code Playgroud)

我正在使用 Windows 和 LLVM 的 x64 windows 二进制文件。

GCC 打印 146(如预期),但 clang 生成的代码打印随机值,为什么?在 Windows 上使用 gdb 调试 clang 二进制文件显然存在一些问题,因此我无法提供任何 gdb 日志。GCC 二进制文件正在执行我期望的操作,但不是 Clang。

c assembly x86-64 calling-convention

0
推荐指数
1
解决办法
86
查看次数

movss操作码需要如何解释?

我在 Visual Studio IDE 的调试器上从 C++ 构建中获得了以下反汇编代码:

在此输入图像描述

根据我在movss指令上看到的内容,应该是

  1. F3 0F 10 /r MOVSS xmm1, xmm2 -- 将标量单精度浮点值从 xmm2 合并到 xmm1 寄存器。
  2. F3 0F 10 /r MOVSS xmm1, m32 - 将标量单精度浮点值从 m32 加载到 xmm1 寄存器。
  3. F3 0F 11 /r MOVSS xmm2/m32, xmm1 -- 将标量单精度浮点值从 xmm1 寄存器移至 xmm2/m32。

因此,虽然前 3 个字节很容易理解,但我不太理解其余的字节,例如05 6b 02 10 00第一行、44 24 38第二行等等。

你能帮我理解它们吗?05或44好像是/r?这是什么意思?

assembly x86-64 disassembly

0
推荐指数
1
解决办法
73
查看次数