标签: x86-64

如何反转符号扩展?

我用 将两个数字相乘imulq。它在 上返回一个有符号的数字rdx:rax。我想把它压缩到rax寄存器中。基本上,我正在寻找反转cqo.

assembly x86-64 att

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

main 与 _start 中的返回值

请注意,这个问题在这里已经有类似的答案,我想指出:

然而,这个问题更多地询问它们的返回格式以及它们如何相互关联(我认为上面的问题没有完全涵盖)。


_start和之间有什么区别main?在我看来,像ld用途_start,但gcc用途main为切入点。我注意到的另一个区别是main似乎返回值 in %rax,而_start返回值 in%rbx

以下是我看到的两种方式的示例:

.globl _start
_start:
    mov $1, %rax
    mov $2, %rbx
    int $0x80
Run Code Online (Sandbox Code Playgroud)

并运行它:

$ as script.s -o script.o; ld script.o -o script; ./script; echo $?
# 2
Run Code Online (Sandbox Code Playgroud)

另一种方式:

.globl main
main:
    mov $3, %rax
    ret
Run Code Online (Sandbox Code Playgroud)

并运行它:

$ gcc script.s -o script; ./script; echo $?
3
Run Code Online (Sandbox Code Playgroud)

这两种方法有什么区别?是否main自动调用_start某处,或者它们如何相互关联?为什么一个返回它们的值,rbx而另一个返回它的值rax …

c assembly program-entry-point x86-64

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

强制 RIP 相对寻址?

有没有办法强制编译器或汇编器只生成 RIP 相关的寻址代码?

我试图找到一种方法来提供从传统编程模型到图灵完备抽象计算模型的映射。

assembly x86-64 machine-language machine-code relative-addressing

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

C 非法指令

下面是我写的 ac 程序的打印件,我运行它的演示,最后是关于我的编译器的一些信息。

?  illegalInstructionDebug cat illegal.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void func(int* Z){
    Z[-11] = acos(2);
}

int main(){
    fflush(stdout);
    printf("");
    fflush(stdout);
    int X[3];
    int Z[3];
    for (int n=0;0!=0;);
    func(Z);
}
?  illegalInstructionDebug gcc illegal.c; ./a.out
[1]    28836 illegal hardware instruction  ./a.out
?  illegalInstructionDebug clang --version
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
?  illegalInstructionDebug
Run Code Online (Sandbox Code Playgroud)

我在编写一个程序时遇到了一个非法指令错误,这是我以前从未见过的,所以我决定尝试找到一个最小的工作示例,以便我可以找出它与段错误或其他类型错误的区别。奇怪的是,程序中的微小更改似乎会使它返回段错误而不是非法指令错误。尽管如此,我还是设法将程序大幅缩减为一个较小的工作示例。话虽如此,对于一个最小的工作示例来说,该程序仍然相当大。

我的问题首先是为什么我会收到非法指令错误,其次是什么是非法指令错误。此外,如果此错误特定于我的机器,我也会感兴趣。这个程序有很多奇怪的属性。例如,似乎需要数字 -11 才能导致错误。

c x86-64 undefined-behavior illegal-instruction

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

什么时候可以在 x86-64 模式下使用 lahf?

所述的描述LAHF指令为:

该指令在兼容模式和传统模式下如上所述执行。仅当 CPUID.80000001H:ECX.LAHF-SAHF[bit 0] = 1 时才在 64 位模式下有效

第一个问题:什么是兼容性和传统模式。它们与实模式和保护模式有何不同

第二个问题:CPUID.80000001H:ECX.LAHF-SAHF[bit 0] = 1是什么意思

谢谢!!!

assembly x86-64 cpuid

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

为什么 %rax 寄存器在这个程序的程序集中使用 8 个参数?

我有以下 C 函数:

void proc(long  a1, long  *a1p,
          int   a2, int   *a2p,
          short a3, short *a3p,
          char  a4, char  *a4p)
{
    *a1p += a1;
    *a2p += a2;
    *a3p += a3;
    *a4p += a4;
}
Run Code Online (Sandbox Code Playgroud)

使用Godbolt,我已将其转换为 x86_64 程序集(为简单起见,我使用该-Og标志来最小化优化)。它产生以下组件:

proc:
        movq    16(%rsp), %rax
        addq    %rdi, (%rsi)
        addl    %edx, (%rcx)
        addw    %r8w, (%r9)
        movl    8(%rsp), %edx
        addb    %dl, (%rax)
        ret
Run Code Online (Sandbox Code Playgroud)

我对汇编的第一行感到困惑:movq 16(%rsp), %rax. 我知道%rax寄存器用于存储返回值。但是该proc过程没有返回值。所以我很好奇为什么在此处使用该寄存器,而不是 %r9其他一些不用于返回值的寄存器。

相对于其他指令,我也对这条指令的位置感到困惑。它首先出现,远在%rax任何需要其目标寄存器之前(实际上,直到最后一步才需要该寄存器)。它也出现在 之前addq %rdi, (%rsi) …

assembly x86-64 cpu-registers compiler-optimization

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

创建带有只读标志的程序头会导致段错误

我一直在使用 NASM 编写 ELF 二进制文件,并创建了一个打开只读标志的段。运行程序会导致段错误。我在 replit 中测试了该程序,它运行得很好,所以有什么问题?我在 .rodata 部分创建了一个带有 hello world 字符串的常规 NASM hello world 程序,并且运行良好。我用 readelf 检查了二进制文件以确保字符串在只读段中。

我想出的唯一解决方案是在 Rodata 段中设置可执行标志,以便它具有读取/执行权限,但这很糟糕,我希望 Rodata 段是只读的。

这是 ELF-64 hello world 的代码。

; hello.asm
[bits 64]
[org 0x400000]

fileHeader:
    db 0x7F, "ELF"
    db 2 ; ELF-64
    db 1 ; little endian
    db 1 ; ELF version
    db 0 ; System V ABI
    db 0 ; ABI version
    db 0, 0, 0, 0, 0, 0, 0 ; unused
    dw 2 ; executable object file
    dw …
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 elf

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

EFLAGS 状态

在过去的几天里,我一直在为一种试图获得 EFLAGS 状态的奇怪行为而苦苦挣扎。为此,我编写了以下代码:

#include <stdio.h>

int flags_state()
{

  int flags = 0;

  __asm__ __volatile__("pushfq");
  __asm__ __volatile__("pop %%rax": "=a"(flags));

  return flags;
}

int main()
{

  printf("Returning EFLAGS state: 0x%x\n", flags_state());
  return 0;

}
Run Code Online (Sandbox Code Playgroud)

当它运行时,我得到:

./flags
Returning EFLAGS state: 0x246
Run Code Online (Sandbox Code Playgroud)

当我打印两次标志时,它变得更奇怪了

Returning EFLAGS state: 0x246
Returning EFLAGS state: 0x206
Run Code Online (Sandbox Code Playgroud)

当我尝试打印 6 次时它发生了变化

Returning EFLAGS state: 0x246
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Returning EFLAGS state: 0x202
Run Code Online (Sandbox Code Playgroud)

最后是最奇怪的(至少对我来说),当我打印 8 次时

Returning EFLAGS state: …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 inline-assembly eflags

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

为什么 GCC 8/9/10 和 GCC-7 在计算堆栈偏移量时表现不同?

我正在将代码移植到现代编译器,不幸的是,当从 Rust 调用 FFI 函数到 C++ 时遇到了一个微妙的分段错误。

堆栈跟踪显示,在过渡到 C++ 之后,Rust 提供的第一个参数神奇地消失了,这会误导 C++ 使用错误的参数。

代码有点私密,所以我不能在这里发布,但程序集显示了一些有趣的东西:

在 GCC-7(代码运行没有问题)中,汇编的前几行如下所示:

   0x0000000000001119 <+0>:     push   rbp
   0x000000000000111a <+1>:     mov    rbp,rsp
   0x000000000000111d <+4>:     push   r13
   0x000000000000111f <+6>:     push   r12
   0x0000000000001121 <+8>:     push   rbx
   0x0000000000001122 <+9>:     sub    rsp,0x128
   0x0000000000001129 <+16>:    mov    QWORD PTR [rbp-0x118],rdi
   0x0000000000001130 <+23>:    mov    rax,rsi
   0x0000000000001133 <+26>:    mov    rsi,rdx
   0x0000000000001136 <+29>:    mov    rdx,rsi
   0x0000000000001139 <+32>:    mov    QWORD PTR [rbp-0x130],rax
   0x0000000000001140 <+39>:    mov    QWORD PTR [rbp-0x128],rdx
   0x0000000000001147 <+46>:    mov    QWORD PTR [rbp-0x120],rcx
   0x000000000000114e <+53>:    mov    QWORD …
Run Code Online (Sandbox Code Playgroud)

c++ gcc x86-64 abi rust

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

如何在 ARM M1 Apple Silicon Mac 上将 Rust 代码交叉编译为 Intel 程序集?

我一直在比较 C 和 Rust 为 x86 和 ARM 生成的汇编代码。

我有一台 M1 Mac,我找到了如何用 Clang 交叉编译 C,但到目前为止我找不到如何交叉编译 Rust。

如何在 M1 Mac 上从 Rust 生成 x86_64 二进制文件?

macos x86-64 cross-compiling rust

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