标签: gnu-assembler

如何在 GAS 汇编程序中导出函数?

嗨,我有以下汇编代码,

.export __ls__11NSDOM_EncapFf
.text 
__ls__11NSDOM_EncapFf:
/* first load the symbolic constant*/
movq _IEEE_FP@GOTPCREL(%rip), %r8  /*%r8 is a scratch register*/
movq (%r8), %r9  /* %r9 and %r11 are scratch registers*/
movl (%r9), %r11d
/* second, see if it is zero and branch accordingly */
test %r11d, %r11d   /* zero call TNS procedure */
                    /* non-zero call IEEE procedure */
je  ____ls__11NSDOM_EncapFf_tns/* constant equals 0 */
jmp  ____ls__11NSDOM_EncapFf_ieee/* constant not equal to 0 */
ret
Run Code Online (Sandbox Code Playgroud)

我将 .s 文件编译为 .o 文件(编译很好),但是当我将此 .o 与其他 …

assembly x86-64 gnu-assembler

4
推荐指数
2
解决办法
3177
查看次数

将内联汇编与 C 代码混合 - 如何保护寄存器并最小化内存访问

我有一个例程,主要想用汇编语言编写,但我需要调用 C 函数来获取处理所需的一些数据。在某些情况下,我可以预先消化数据并加载带有指向它的指针的寄存器,但在其他情况下,我必须调用完整的函数,因为可能的数据集太大。这些函数无法修改,因为它们是别人的代码,并且其接口需要与其他代码保持相同。其中一些驻留在共享库中,尽管有些是通过头文件的内联函数(我无法更改)。

我可以使用 asm 构造将局部变量分配给寄存器:

register int myReg asm( "%r13" );
Run Code Online (Sandbox Code Playgroud)

恐怕如果我直接在汇编中操作 %r13,调用 C 函数并返回,它将需要从内存中刷新,或者更糟糕的是被完全覆盖。对于某些 ABI,我自己直接推送/弹出寄存器也不安全,对吗?我在 Linux 上使用 x86-64 工作。

我现在正在做的事情似乎正在使用 -g -O0,但我担心当我打开 C 代码的优化时,它将开始触及我希望受到保护的寄存器。

一般来说,我的代码流程如下:

asm( "movq %[src], %%r13" : : [src] "m" (myVariablePointer) : "r13" );

localVariable1 = callSomeCfunction( stuff );

storageLocation = index * sizeof( longTermStorageItem );
longTermStorage[storageLocation] = localVariable1;
// some intermediate registers need to be used here for dereferences and math

switch ( localVariable1 )
{
   case CONSTANT_VAL_A:
     C_MACRO_LOOP_CONSTRUCT
     {
       asm( "movdqa (%r13), %xmm0\n" …
Run Code Online (Sandbox Code Playgroud)

gcc x86-64 gnu-assembler inline-assembly

4
推荐指数
1
解决办法
3283
查看次数

GCC内联汇编中的"= w"是什么意思?

我发现asm内联汇编正在工作,我无法理解(链接):

// busy wait
__asm__ __volatile__ (
    "1: sbiw %0,1" "\n\t" // 2 cycles
    "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
Run Code Online (Sandbox Code Playgroud)

我已经发现了一些气体教程像这样,但我无法找到解释.无论如何,文件可以由avr-gcc编译:

/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu = atmega328p -DF_CPU = 16000000L -MMD -DUSB_VID = null -DUSB_PID = null -DARDUINO = 105 -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino -I/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/variants/standard /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/wiring.c -o /var/folders/64/fwfkm1k51zbd4_c5lwpsbljh0000gn/T/build5450310618632673119.tmp/wiring.co

那么GCC内联汇编中的"= w"是什么意思呢?

c assembly gcc gnu-assembler

4
推荐指数
2
解决办法
295
查看次数

无效的基/索引表达式

尝试使用基索引表达式在 16 位实模式下操作内存会导致编译错误:

movw    $0xd000, -2(%sp)
movw    $0, -4(%sp)
movw    $1, -6(%sp)
Run Code Online (Sandbox Code Playgroud)

编译为

gcc -c -Wa,--32 $(DIR_BS_SRC)/mbr.S -o $(DIR_BS_SRC)/mbr.o
ld -nostdlib --oformat binary --Ttext 0x7c00 $(DIR_BS_SRC)/mbr.o -o $(DIR_B$
Run Code Online (Sandbox Code Playgroud)

产生以下错误:

bootsector/src/mbr.S:20: Error: `-2(%sp)' is not a valid base/index expression
bootsector/src/mbr.S:21: Error: `-4(%sp)' is not a valid base/index expression
bootsector/src/mbr.S:22: Error: `-6(%sp)' is not a valid base/index expression
Run Code Online (Sandbox Code Playgroud)

我认为这是有效的语法,即使在 16 位实模式下也是如此?

x86 assembly real-mode gnu-assembler

4
推荐指数
1
解决办法
5677
查看次数

使用 gas (-fPIC) 生成位置无关代码

我尝试在 x86-64 上创建一个共享库,但失败了。问题归结为以下代码(请不要介意,它没有多大意义):

.section .data
newline:
    .ascii "\n"

.section .text
.globl write_newline
    .type write_newline, @function
write_newline: 
    mov  $newline, %rax    
    ret
Run Code Online (Sandbox Code Playgroud)

建筑如下:

as minimal.s -o minimal.o
ld -shared minimal.o -o libmin.so
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

ld: minimal.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
minimal.o: error adding symbols: Bad value
Run Code Online (Sandbox Code Playgroud)

但是gas不知道选项-fPIC,所以我不能用它重新编译:

as -fPIC minimal.s -o minimal.o
as: unrecognized option '-PIC'
Run Code Online (Sandbox Code Playgroud)

可以做些什么呢?

assembly gnu-assembler shared-libraries

4
推荐指数
1
解决办法
2478
查看次数

GNU 等同于时间 X db 0

我正在 GNU 中编写一个小型引导加载程序as,我需要使二进制输出“与 BIOS 兼容”。这是我如何做到的nasm

...
times 510 - ($-$$) db 0
dw 0xAA55
Run Code Online (Sandbox Code Playgroud)

但是我怎么能在 GNU 中做到呢as

gnu gnu-assembler nasm

4
推荐指数
1
解决办法
897
查看次数

X86 intel 语法 - mov 大小不明确,表达式后为垃圾 h?

我正在使用 AT&T 语法,但我想尝试一下英特尔。我有这个代码:

.text
        .global _start

_start: 
        mov ebx, 0
        mov eax, 1          
        int 80h
Run Code Online (Sandbox Code Playgroud)

哪个应该返回0,对吗?在我转换它之前,它是用 AT&T 做的。

我正在组装使用:

 as out.s -msyntax=intel --32 -o out.o
Run Code Online (Sandbox Code Playgroud)

但我得到:

out.s:5: Error: ambiguous operand size for `mov'
out.s:6: Error: ambiguous operand size for `mov'
out.s:7: Error: junk `h' after expression
Run Code Online (Sandbox Code Playgroud)

我哪里出错了?

x86 gnu-assembler att intel-syntax

4
推荐指数
1
解决办法
4245
查看次数

GAS ARM 目标下的注释语法歧义

GNU GAS 文档似乎无法正确定义 ARM 目标的某些语法功能,因此我在编写简单的汇编时都遇到困难。

\n\n

两个这样的例子:

\n\n
    \n
  • ARM编译器迁移和兼容性指南 6.02 版指出,在 GNU 语法下,以及多行注释:

    \n\n
    \n

    //标记将一行的剩余部分标识为注释:

    \n\n

    MOV R0,#16 // Load R0 with 16

    \n
    \n\n

    这似乎与使用指南相冲突,其中指出:

    \n\n
    \n

    行中任意位置出现 \xe2\x80\x98@\xe2\x80\x99 表示注释的开始,并延伸到该行的末尾。

    \n
  • \n
  • 指令中隐式转换的问题仅在 Arm 文档中得到解决,并且仅给出失败的情况:

    \n\n
    \n

    GNU 语法汇编期望立即值以编码形式呈现。该指令MOVK x1, #0x40000会产生以下消息:error: immediate must be an integer in range [0, 65535].

    \n
    \n\n

    “编码”到底是什么意思?我是否可以假设LSLGNU 下同样支持该语法?GAS 文档中似乎没有解决这个问题。

  • \n
\n\n

有没有地方可以找到 GAS + ARM 目标的具体且完整的语法定义?\n提前致谢。

\n

assembly arm gnu-assembler

4
推荐指数
1
解决办法
444
查看次数

ascii vs asciz vs 气体字符串

.ascii.asciz、 和之间有什么区别。string在气体中?在我看来很清楚:

  • .ascii是这样的char[],所以.ascii "hello"会转化为0x48 0x65 0x6c, 0x6c, 0x6f
  • .asciz是相同的,但nul在末尾添加了 a ,因此.asciz "hello"将转换为0x48 0x65 0x6c, 0x6c, 0x6f 0x00

但是,.string与上述两种有什么区别,为什么要使用另一种呢?

x86 assembly gnu-assembler

4
推荐指数
1
解决办法
332
查看次数

如果我在 x86 AT&T 语法中省略了比例因子和索引寻址模式,会发生什么?

我是组装新手,我正在从头开始编程学习它。在第 41 页和第 42 页,该书讨论了索引寻址模式。

内存地址引用的一般形式是: ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
所有字段都是可选的。要计算地址,只需执行以下计算:
FINAL ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
ADDRESS_OR_OFFSET 和 MULTIPLIER 必须都是常量,而另外两个必须是寄存器。如果任何部分被遗漏,它只是在等式中用零代替。

所以我决定稍微玩一下这个。我写了下面的一段代码:

.code32
.section .data
str:
    .ascii "Hello world\0"

.section .text
.global _start
_start:
    movl $2, %ecx       # The index register.
    mov str(, %ecx, ), %bl
    movl $1, %eax
    int $0x80

Run Code Online (Sandbox Code Playgroud)

我希望得到 72(H 的 ASCII 代码)作为程序的退出结果,因为没有任何乘数(根据这本书,应该用零代替)。但令人惊讶的是,我得到了 108(l 的 ASCII 代码)。我认为这可能是.ascii一回事,并试图查看是否可以使用不同的数据类型获得不同的结果。我得到了相同的结果.byte

我尝试使用 AT&T 语法在 x86 程序集中查找索引寻址模式,但找不到任何有用的信息(可能是因为我不知道要搜索什么)。

有什么我遗漏的或者是书中的错误吗?鉴于我是该领域的新手,如果您详细说明,我真的很感激。

x86 assembly gnu-assembler att addressing-mode

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