有谁知道 GAS 教程,我可以在其中找到有关在 64 位系统上在 AT&T 语法中编译和链接代码的信息?我在大学需要这个,所以我不能使用 nasm 代替。我能找到的所有 Tuts 要么适用于 nasm 或类似的东西,要么只能在 32 位上运行。即使我们的教授展示的简约示例也适用于我的 32 位系统,但不适用于 64 位系统。
如何生成可直接在 CPU 上运行的平面二进制文件?
也就是说,没有操作系统;也称为独立环境代码(请参阅在没有操作系统的情况下直接运行的程序的名称是什么?)。
我注意到我正在使用的as来自 OS-X 开发人员工具包的汇编器不断生成 Mach-O 文件,而不是平面二进制文件。
我有一个内联函数定义,它包装了一个内联程序集。我希望根据参数在构建时是否已知的事实来选择不同的内联汇编实现。
我的问题是如何在 C 代码或内联汇编中询问地址值在构建时是否已知,因此适合作为立即值。如果您正在考虑 __builtin_constant_p - 请继续阅读。
这是一些说明我的意图的代码:我正在尝试找到一种方法来实现“is_immediate”。
static char arr[5];
void __attribute__((always_inline)) do_something(char * buf)
{
if(is_immediate(buf) {
// Argument is constant, can use immediate form
asm volatile ("insn1 %0" : : "i"(buf));
} else {
// Argument is computed at runtime, use a register
unsigned long tmp = (unsigned long)buf + 1;
asm volatile("insn2 %0" : : "r"(tmp));
}
int main(void)
{
do_something(&arr);
}
Run Code Online (Sandbox Code Playgroud)
乍一看,__builtin_constant_p() 似乎正是所需的魔法,但它不起作用。
不起作用的原因是,虽然在链接器将数组放入内存并为其选择地址后就知道数组的地址(因此它确实符合内联汇编的直接约束),但它不是在链接之前的编译时已知。
因此,我正在寻找一种方法来询问“这个变量是否适合作为立即值?” 而不是“这是一个常量表达式吗?”。
我正在尝试使用内联汇编将一堆结构成员(Particle是指向此类结构的指针)加载到某些寄存器中。这是我最初的解决方案:
asm("mov %1(%0), %%edx\n"
"fld %2(%0)\n"
"fld %3(%0)\n"
"fld %4(%0)\n"
"fld %5(%0)\n"
"movups %6(%0), %%xmm1\n"
"movups %7(%0), %%xmm2\n"
"movups %8(%0), %%xmm3\n"
"movups %9(%0), %%xmm4\n"
:
: "r" (Particle),
"n" (offsetof(ptcParticle, Active)),
"n" (offsetof(ptcParticle, Size)),
"n" (offsetof(ptcParticle, Rotation)),
"n" (offsetof(ptcParticle, Time)),
"n" (offsetof(ptcParticle, TimeScale)),
"n" (offsetof(ptcParticle, Colour)),
"n" (offsetof(ptcParticle, Location)),
"n" (offsetof(ptcParticle, Velocity)),
"n" (offsetof(ptcParticle, Accel))
: "%edx", "%st", "%st(1)", "%st(2)", "%st(3)", "%xmm1", "%xmm2",
"%xmm3", "%xmm4"
);
Run Code Online (Sandbox Code Playgroud)
但它不起作用,因为 GCC 将这些偏移量输出为立即数字文字,如下所示:
mov $0(%eax), %edx
fld $44(%eax)
fld $40(%eax)
fld $8(%eax) …Run Code Online (Sandbox Code Playgroud) 如何mov [ebx], al从 NASM 转换为 GAS?我尝试过mov %al, (%ebx),但确实存在分段错误。
另一个问题,假设我在 GAS 中有一个数组,我是否必须像这样.lcomm array, 50
输入美元($)符号:或者不需要?arraymov %rbx, $array
任何答案都会有帮助:)
例如:
a = 1
Run Code Online (Sandbox Code Playgroud)
和:
.equ a, 1
Run Code Online (Sandbox Code Playgroud)
和:
.set a, 1
Run Code Online (Sandbox Code Playgroud)
所有这些都在以下情况下逐字节产生相同的输出:
as --32 main.S
Run Code Online (Sandbox Code Playgroud)
根据cmp。
我知道这一点.equ,并.set根据以下文档执行相同的操作.equ:https://sourceware.org/binutils/docs-2.25/as/Equ.html:
它与“.set”同义。
我知道ARM 汇编中 .equ 和 .word 之间的区别.equ是什么?
那么呢=?和另外两个一样吗?
我是 64 位 x86 编码新手,但我运行的是 Ubuntu 14.04(可靠),并且我有一段非常简单的 64 位代码,我使用as进行汇编。我得到的输出具有奇怪的权限和文件类型。
当我跑步时:
as file.s
Run Code Online (Sandbox Code Playgroud)
我得到一个具有 770 权限的文件a.out。
当我执行它时,我得到这个错误:
bash: ./a.out: 无法执行二进制文件: Exec 格式错误
当我跑步时:
file ./a.out
Run Code Online (Sandbox Code Playgroud)
我得到:
./a.out:ELF 64 位 LSB 可重定位,x86-64,版本 1 (SYSV),未剥离
我使用的汇编代码是:
.section .data
.LC0:
.string "/bin/sh"
.LC1:
.string "/bin/sh"
.LC3:
.quad .LC1, 0
.text
.globl _start
_start:
.LFB0:
pushq %rbp
movq %rsp, %rbp
movq $59,%rax # System Call to execve
movq $.LC0, %rdi # Pass program to execute
movq $.LC3, %rsi # Pass command …Run Code Online (Sandbox Code Playgroud) 我使用 GNU 汇编器和 AT&T 语法编写了我的第一个引导加载程序。它应该打印hello world到屏幕上,然后通知用户按任意键将导致重新启动。只有按下某个键后才会启动重新启动。我的引导加载程序代码不等待按键,并在打印信息后自动重新启动。为什么此代码不等待击键,我该如何修复它?
我的引导扇区代码:
#generate 16-bit code
.code16
#hint the assembler that here is the executable code located
.text
.globl _start;
#boot code entry
_start:
jmp _boot #jump to boot code
welcome: .asciz "Hello, World\n\r" #here we define the string
AnyKey: .asciz "Press any key to reboot...\n\r"
.macro mWriteString str #macro which calls a function to print a string
leaw \str, %si
call .writeStringIn
.endm
#function to print the string
.writeStringIn:
lodsb
orb %al, %al …Run Code Online (Sandbox Code Playgroud) 我试图了解这段内联汇编的作用,它是从 CDEFINE宏生成的:
#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
Run Code Online (Sandbox Code Playgroud)
它被用于在linux-imxsmc内核分支中进行 AArch64 调用。使用上述 C 宏定义值的地方是:
// arch/arm64/kernel/asm-offsets.c
int main(void)
{
(...)
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
(...)
}
Run Code Online (Sandbox Code Playgroud)
后来,这些定义在汇编宏中使用,可在此处使用(或者至少看起来像这样):
// arch/arm64/kernel/smccc-call.S
.macro SMCCC instr
.cfi_startproc
\instr #0
ldr x4, [sp]
stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
stp x2, x3, [x4, …Run Code Online (Sandbox Code Playgroud) 当使用 GNU GAS 手动编写程序集时,在函数内,我想设置一个标签,以便:
b mylabel打破标签类似的问题nasm已在以下位置提出:Break at local label using GDB for NASM assembly,但我想在这里更精确地表示我想要 GNU GAS 和 ELF 输出。
例如,如果我定义了一个普通标签,mylabel如下所示:
电源
.text
.global _start
_start:
/* exit */
mov $60, %rax
mylabel:
mov $0, %rdi
syscall
Run Code Online (Sandbox Code Playgroud)
这并不令我满意,因为当 GDB 到达 时mov $0, %rdi,bt显示mylabel为函数名称,而我希望它是函数_start名称。特别是,这可能会破坏回溯,因为 GDB 无法找到堆栈帧:How gdbreconstructing stacktrace for C++?
但是,如果我按照以下解释替换mylabel为.Lmylabel:Local labels in GNU assembler; gdb 打印回溯,就像标签是函数一样, …