标签: gnu-assembler

x86-64 GAS Intel 语法中像“[RIP + _a]”这样的 RIP 相关变量引用如何工作?

考虑 x64 Intel 程序集中的以下变量引用,其中变量a.data节中声明:

mov eax, dword ptr [rip + _a]
Run Code Online (Sandbox Code Playgroud)

我很难理解这个变量引用是如何工作的。既然a是对应于变量运行时地址的符号(带重定位),如何[rip + _a]解引用正确的内存位置a?事实上,rip保存当前指令的地址,它是一个大的正整数,所以加法会导致错误的地址a

相反,如果我使用 x86 语法(非常直观):

mov eax, dword ptr [_a]
Run Code Online (Sandbox Code Playgroud)

,我收到以下错误:64 位模式不支持 32 位绝对寻址

有什么解释吗?

  1 int a = 5;
  2 
  3 int main() {
  4     int b = a;
  5     return b;
  6 }   
Run Code Online (Sandbox Code Playgroud)

编译gcc -S -masm=intel abs_ref.c -o abs_ref::

  1     .section    __TEXT,__text,regular,pure_instructions
  2     .build_version macos, 10, 14
  3 …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 gnu-assembler intel-syntax addressing-mode

14
推荐指数
1
解决办法
2893
查看次数

如何在不使用gcc的情况下将使用C标准库的气体组件程序与ld链接?

作为一个练习来更准确地学习c程序如何工作以及程序能够使用libc必须存在的最低内容级别,我自己尝试使用gas和ld主要在x86程序集中进行编程.

作为一个有趣的小挑战,我已成功组装并链接了几个链接到不同自制动态库的程序,但是我无法从头开始编写程序以使用libc函数调用而无需直接使用gcc.

我了解单个c库函数的调用约定,并通过使用objdump和readelf彻底检查了gcc编译的程序,但是在气体汇编文件中包含哪些信息以及要调用的参数方面没有任何进展在ld中成功链接到libc.有人对此有任何见解吗?

我在x86机器上运行Linux.

assembly gnu-assembler ld binutils

13
推荐指数
2
解决办法
8854
查看次数

内部搬迁没有修好

我最近开始使用arm core进行汇编编程.我的第一个小演示,只有.text部分,没有任何问题.

作为一个逻辑扩展,我想将汇编代码构造成通常的部分:.text,.data,.bss.

所以我写了以下简单的程序:

 .globl _start

 .section .text

 _start:
     b   main
     b   .
     b   .
     b   .
     b   .
     b   .
     b   .
     b   .  


 main:
    ldr r0, x
    nop

 .section .data

 x:  .word  0xf0f0f0f0

 .end
Run Code Online (Sandbox Code Playgroud)

  /opt/arm/bin/arm-as -ggdb -mcpu=arm7tdmi demo.s -o demo.o
Run Code Online (Sandbox Code Playgroud)

退出并出错

 prog.s: Assembler messages:
 prog.s:17: Error: internal_relocation (type: OFFSET_IMM) not fixed up
 make: *** [prog.o] Error 1
Run Code Online (Sandbox Code Playgroud)

我不知道为什么汇编程序抱怨重定位,因为我认为这是链接器的任务.我可以想象我必须告诉汇编程序我的.data部分不是在汇编阶段的最终内存位置,但我找不到任何相关的东西.

虽然我找到了一种方法来通过替换来正确组装代码

 .section .data
Run Code Online (Sandbox Code Playgroud)

通过

 .org .
Run Code Online (Sandbox Code Playgroud)

这不是一个令人满意的解决方案.特别是考虑到气体文件突出了这一部分的意义.

也许你的专家可以帮助我获得一些智慧

assembly arm gnu-assembler

13
推荐指数
2
解决办法
2万
查看次数

GCC内联汇编程序,混合寄存器大小(x86)

有谁知道如何摆脱以下汇编警告?

代码是x86,32位:

int test (int x)
{
  int y;
  // do a bit-rotate by 8 on the lower word. leave upper word intact.
  asm ("rorw $8, %0\n\t": "=q"(y) :"0"(x));
  return y;
}
Run Code Online (Sandbox Code Playgroud)

如果我编译它,我得到以下(非常有效)警告:

Warning: using `%ax' instead of `%eax' due to `w' suffix
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是告诉编译器/汇编器我想要访问%0的低16位子寄存器的方法.访问字节子寄存器(在本例中为AL和AH)也很好.

我已经选择了"q"修饰符,因此编译器被迫使用EAX,EBX,ECX或EDX.我已经确保编译器必须选择一个具有子寄存器的寄存器.

我知道我可以强制asm-code使用特定的寄存器(及其子寄存器),但我想将寄存器分配作业留给编译器.

x86 assembly gcc gnu-assembler

12
推荐指数
2
解决办法
5792
查看次数

是否可以在C中编写零成本异常处理?

g ++编译器具有零成本异常处理功能.据我所知,try什么都不做,但是当抛出异常时,会执行异常处理程序的子例程.像这样:

void foo() {
    try {
        bar(); // throws.
    } catch (Type exc) {
        baz();
    }
}
Run Code Online (Sandbox Code Playgroud)

伪代码(c-stylish)看起来像这样:

void foo() {
    bar();
    return;
catch1_Type:
    baz();
}
Run Code Online (Sandbox Code Playgroud)

bar()抛出.例程例程执行以下操作:

啊,返回地址是函数foo()!并且返回地址在第一个try-catch块中,我们抛出类型Type,因此异常处理程序例程位于地址foo + catch1_Type.所以清理堆栈让我们最终到达那里!

现在我的问题是:有没有办法在C中实现它?(可以是C99或更新,虽然我对gcc支持的C语言感兴趣).我知道我可以使用例如libunwind进行堆栈检查和遍历,虽然我不知道如何获取catch1_Type标签的地址.这可能是不可能的.

异常处理程序可能是一个不同的函数,同样可以,但是如何foo在另一个函数中获取stackframe的局部变量的地址?这似乎也是不可能的.

所以...有什么办法吗?我不想用这个进入汇编程序,但如果其他一切都失败也是可以接受的(尽管局部变量 - 伙计,如果使用不同的优化级别,你永远不会知道它们在哪里).

并且要明确 - 这个问题的目的是避免使用 setjmp/longjmp方法.

编辑:我发现了一个非常酷的想法,但完全不起作用:

gcc中的嵌套函数.他们能做什么?

  • 有权访问局部变量,
  • 有可能在父函数中转到本地标签!
  • 只要我们传递指向嵌套函数的指针,我们函数的被调用者就可以调用它,因此它可以被被调用者中的指针使用.

下行阻止我做任何零成本的事情:

  • 如果它们未使用,它们甚至会在-O0级别进行优化.我可以对此做些什么吗?如果可以的话,我可以在抛出异常时通过符号名称获取地址,并且它只是执行实现异常的工作,这些异常在不抛出时会花费成本...

c optimization exception-handling gnu-assembler elf

12
推荐指数
1
解决办法
1260
查看次数

如何使用GCC生成最小的BIOS hello world启动扇区,它可以在真实硬件上使用USB记忆棒?

我设法生成一个与QEMU 2.0.0 Ubuntu 14.04一起使用的最小引导扇区:

.code16
.global _start
_start:
    cli
    mov $msg, %si
    mov $0x0e, %ah
loop:
    lodsb
    or %al, %al
    jz halt
    int $0x10
    jmp loop
halt:
    hlt
msg:
    .asciz "hello world"
.org 510
.word 0xaa55
Run Code Online (Sandbox Code Playgroud)

编译:

as -o main.o main.S
ld --oformat binary -o main.img -Ttext 0x7C00 main.o
Run Code Online (Sandbox Code Playgroud)

这个例子可以在这个回购中找到:https://github.com/cirosantilli/x86-bare-metal-examples/tree/2b79ac21df801fbf4619d009411be6b9cd10e6e0/no-ld-script

一旦:

qemu -hda main.img
Run Code Online (Sandbox Code Playgroud)

hello world按预期在模拟器屏幕上显示.

但是,如果我尝试刻录到USB:

sudo dd if=main.img of=/dev/sdb
Run Code Online (Sandbox Code Playgroud)

然后将USB插入ThinkPad T400或T430,点击F12,然后选择我观察到的USB:

  • 一些启动消息很快显示出来
  • 然后屏幕变为空白,顶部只有一个下划线光标

我也用Ubuntu 14.04映像测试了相同的USB,它启动正常,因此USB工作正常.

我应该如何更改此示例,以便它将在硬件上启动并显示hello world消息?

Ubuntu图像和我创建的图像有什么区别?

这记录在哪里?

我已将sudo dmidecodeT400 …

x86 assembly qemu gnu-assembler bare-metal

12
推荐指数
1
解决办法
2402
查看次数

了解基指针和堆栈指针:在gcc输出的上下文中

我有以下C程序:

int main()
{
    int c[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2};
    return c[0];
}
Run Code Online (Sandbox Code Playgroud)

当使用带有gcc的-S指令编译时,我得到以下程序集:

    .file   "array.c"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $0, -48(%rbp)
    movl    $0, -44(%rbp)
    movl    $0, -40(%rbp)
    movl    $0, -36(%rbp)
    movl    $0, -32(%rbp)
    movl    $0, -28(%rbp)
    movl    $0, -24(%rbp)
    movl    $0, -20(%rbp)
    movl    $1, -16(%rbp)
    movl    $2, -12(%rbp)
    movl    -48(%rbp), %eax
    leave
    .cfi_def_cfa 7, …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc gnu-assembler

11
推荐指数
1
解决办法
9662
查看次数

gas vs. nasm:哪个汇编程序产生最佳代码?

这两个工具都将汇编指令直接转换为机器代码,但是有可能确定哪一个生成最快,最干净的代码?

assembly gnu-assembler nasm

10
推荐指数
3
解决办法
7340
查看次数

0x4在"movl $ 0x2d,0x4(%esp)"中做了什么?

我正在研究GCC生成的汇编代码.但我不明白:

movl $0x2d, 0x4(%esp)
Run Code Online (Sandbox Code Playgroud)

在第二个操作数中,0x4代表什么?偏移地址?注册EAX有什么用?

c x86 assembly gnu-assembler

10
推荐指数
1
解决办法
7406
查看次数

如何从ARM Assembly调用C函数?

我正在Android设备上编写针对ARM Cortex-A的代码(使用GNU汇编器和编译器),我正在尝试在Assembly和C之间进行接口.特别是,我有兴趣调用用C语言编写的函数.我尝试了很多东西,包括.extern指令,用asm__asm__等声明C函数,但是没有一个工作,所以我正在寻找一个这样做的最小例子.对这样的例子的引用同样值得欢迎.

c assembly arm gnu-assembler cortex-a8

10
推荐指数
1
解决办法
2万
查看次数