嗨,我有以下汇编代码,
.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 与其他 …
我有一个例程,主要想用汇编语言编写,但我需要调用 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) 我发现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"是什么意思呢?
尝试使用基索引表达式在 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-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)
可以做些什么呢?
我正在 GNU 中编写一个小型引导加载程序as,我需要使二进制输出“与 BIOS 兼容”。这是我如何做到的nasm:
...
times 510 - ($-$$) db 0
dw 0xAA55
Run Code Online (Sandbox Code Playgroud)
但是我怎么能在 GNU 中做到呢as?
我正在使用 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)
我哪里出错了?
GNU GAS 文档似乎无法正确定义 ARM 目标的某些语法功能,因此我在编写简单的汇编时都遇到困难。
\n\n两个这样的例子:
\n\nARM编译器迁移和兼容性指南 6.02 版指出,在 GNU 语法下,以及多行注释:
\n\n\n\n\n该
\n\n//标记将一行的剩余部分标识为注释:\n
MOV R0,#16 // Load R0 with 16
这似乎与使用指南相冲突,其中指出:
\n\n\n行中任意位置出现 \xe2\x80\x98@\xe2\x80\x99 表示注释的开始,并延伸到该行的末尾。
\n
指令中隐式转换的问题仅在 Arm 文档中得到解决,并且仅给出失败的情况:
\n\n\n\n\nGNU 语法汇编期望立即值以编码形式呈现。该指令
\nMOVK x1, #0x40000会产生以下消息:error: immediate must be an integer in range [0, 65535].
“编码”到底是什么意思?我是否可以假设LSLGNU 下同样支持该语法?GAS 文档中似乎没有解决这个问题。
有没有地方可以找到 GAS + ARM 目标的具体且完整的语法定义?\n提前致谢。
\n.ascii、.asciz、 和之间有什么区别。string在气体中?在我看来很清楚:
.ascii是这样的char[],所以.ascii "hello"会转化为0x48 0x65 0x6c, 0x6c, 0x6f。.asciz是相同的,但nul在末尾添加了 a ,因此.asciz "hello"将转换为0x48 0x65 0x6c, 0x6c, 0x6f 0x00。但是,.string与上述两种有什么区别,为什么要使用另一种呢?
我是组装新手,我正在从头开始编程学习它。在第 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 程序集中查找索引寻址模式,但找不到任何有用的信息(可能是因为我不知道要搜索什么)。
有什么我遗漏的或者是书中的错误吗?鉴于我是该领域的新手,如果您详细说明,我真的很感激。