在我努力了解如何使用 GNU binutils 使用 Gas构建简单的引导加载程序时,我遇到了一个问题,如何告诉链接器将数据放在使用 .org 推进位置计数器的文件中的位置同时将文件大小保持在 512 字节。我似乎找不到办法做到这一点。
尝试执行此操作的汇编程序是:
# Author: Matthew Hoggan
# Date Created: Tuesday, Mar 6, 2012
.code16 # Tell assembler to work in 16 bit mode
.section .data
msg: # Message to be printed to the screen
.asciz "hello, world"
.section .text
.globl _start # Help linker find start of program
_start:
xor %ax, %ax # Zero out ax register (ah used to specify bios function to Video Services)
movw %ax, %ds # Since …Run Code Online (Sandbox Code Playgroud) jonesforth 通常按如下方式启动:
cat jonesforth.f - | ./jonesforth
Run Code Online (Sandbox Code Playgroud)
有什么好的调试方法吗jonesforth?
当尝试在 Ubuntu 16.04.4 64 位(Xenial Xerus)上构建Jonesforth (32 位 GNU 汇编程序)时,我看到以下内容:
~/src/jonesforth $ make
gcc -m32 -nostdlib -static -o jonesforth jonesforth.S
jonesforth.S:1154:24: fatal error: asm/unistd.h: No such file or directory
compilation terminated.
Makefile:11: recipe for target 'jonesforth' failed
Run Code Online (Sandbox Code Playgroud)
查看文件jonesforth.S,我注意到以下几行:
//#include <asm-i386/unistd.h> // You might need this instead
#include <asm/unistd.h>
Run Code Online (Sandbox Code Playgroud)
我尝试过使用asm-i386/unistd.h它,但这似乎也没有帮助。
最好的做法是通过安装更多标头sudo apt install linux-headers...吗?如果是这样,我应该选择哪个?应该linux-headers-generic够了吧?
jonesforth.S或者,我应该更改所指的标题吗?
有了这个简单的组装:
.text
.globl main
str:
.asciz "%i\n"
add:
push %rbp
mov %rsp, %rbp
movl %esi, %eax
addl %edi, %eax
pop %rbp
ret
main:
mov $1, %esi
mov $2, %edi
lea add(%rip), %rax
call %rax #what is wrong here? the rax should contain first instruction of add
mov %eax, %esi
xor %eax, %eax
lea str(%rip), %rdi
call printf
xor %eax, %eax
ret
Run Code Online (Sandbox Code Playgroud)
我收到错误:
foo.s:17: Warning: indirect call without `*'
Run Code Online (Sandbox Code Playgroud)
为什么?应该%rax包含函数的地址(如注释中所示),这不是c,其中有带有 的指针*,而是包含地址的寄存器。那么这里出了什么问题呢?
.file "test-instr.c"
.text
.Ltext0:
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hum?"
.LC1:
.string "Looks like a zero to me!"
.LC2:
.string "A non-zero value? How quaint!"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
/* --- trampoline malloc shm space begin --- */
.align 4
.section .data
shmSize: .quad 8 * 4 * 0x10000
.global shmptr
shmptr: .quad 0
.section .text
.extern malloc
movq (shmSize), %rdi
call malloc
movq %rax, (shmptr)
/* --- trampoline malloc shm spacd end --- */ …Run Code Online (Sandbox Code Playgroud) 为了获取字符串的长度,我使用以下函数:
string: .asciz "hello world!\n"
get_string_length:
mov $0, %eax # size goes in rax
.L1_loop:
movzbw string(,%eax,1), %ebx
cmp $0, %ebx
je .L1_exit
inc %eax
jmp .L1_loop
.L1_exit:
ret
Run Code Online (Sandbox Code Playgroud)
不过,我也看到了以下情况:
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
Run Code Online (Sandbox Code Playgroud)
以下是如何工作的?这就是.符号和所有得到长度的东西?例如,在此 github 代码片段中:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/9dccafe00d9b0affa8847836a71ebb4c37be7090/userland/arch/x86_64/freestand/linux/hello.S
我正在 GNU 汇编器中编写针对 ARMv8 (AArch64) 的汇编代码。不确定这是否重要,但我直接在运行 Linux 的 ARMv8 目标(Raspberry Pi 板)中进行编码。
\n我有一个带有很长参数列表的宏(例如,超过 60 个参数)——我知道,这是错误的,请不要开枪打我。
\n为了便于阅读,我想将这个参数列表分成多行,即如下所示:
\n.macro my_macro arg1, arg2, arg3, arg4,\n arg5, arg6, arg7, arg8,\n // ...\n arg61, arg62, arg63, arg64\n\n // macro code goes here\n\n.endm\nRun Code Online (Sandbox Code Playgroud)\n我也想在实例化宏时执行相同的操作。
\n不幸的是,当我尝试在宏声明中插入换行符时,我收到以下错误:
\ntest.s: Assembler messages:\ntest.s:123: Error: Bad parameter list for macro `my_macro\'\nRun Code Online (Sandbox Code Playgroud)\n至于在宏实例化中插入换行符,虽然我没有直接收到错误,但代码不会汇编,因为换行符后面的所有参数都被忽略,即好像我用更少的参数实例化了宏比预期的要大,所以缺失的默认为空字符串。
\n根据手册:
\n\n\n可以使用 \xe2\x80\x98;\xe2\x80\x99 字符代替换行符来分隔语句。
\n
;我尝试在每行末尾添加一个,即:
.macro my_macro arg1, arg2, arg3, arg4, ;\n …Run Code Online (Sandbox Code Playgroud) 测试.S
.text
.global _start
_start:
xor %ax, %ax
mov %ax, %ds
mov %ax, %ss
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
Run Code Online (Sandbox Code Playgroud)
我通过这样做得到了反汇编代码文件
$ x86_64-elf-gcc -g -c -O0 -m32 -fno-pie -fno-stack-protector -fno-asynchronous-unwind-tables .\test.S
$ x86_64-elf-ld .\test.o -m elf_i386 -Ttext=0x7c00 -o test.elf
$ x86_64-elf-objdump -x -d -S -m i386 ./test.elf > test_dis.txt
Run Code Online (Sandbox Code Playgroud)
测试_dis.txt
./test.elf: file format elf32-i386
./test.elf
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00007c00
Program Header:
LOAD off 0x00000000 vaddr 0x00007000 paddr 0x00007000 align 2**12
filesz …Run Code Online (Sandbox Code Playgroud) 我正在尝试将我的简单程序从英特尔语法转换为AT&T(用GAS编译).我已经成功转换了我的应用程序的一大部分,但我仍然得到int(中断)的错误.我的功能是这样的:
printf:
mov $0x0e, %ah
mov $0x07, %bl
nextchar:
lodsb
or %al, %al
jz return
int 10
jmp nextchar
return:
ret
msg db "Welcome To Track!", 0Ah
Run Code Online (Sandbox Code Playgroud)
但是当我编译它时,我得到了这个:
hello.S:汇编程序消息:
hello.S:13:错误:int'msg db"Hello,World!",0Ah'的操作数大小不匹配
hello.S:19: Error: no such instruction:
我需要做什么?
我正在尝试用gcc汇编程序扩展做一个非常简单的事情:
在编译我的解决方案时:
#include <stdio.h>
#define inf_int volatile unsigned long long
int main(int argc, char *argv[]){
inf_int zero = 0;
inf_int one = 1;
inf_int infinity = ~0;
printf("value of zero, one, infinity = %llu, %llu, %llu\n", zero, one, infinity);
__asm__ volatile (
"addq $1, %0"
: "=r" (infinity)
);
__asm__ volatile (
"addq $1, %0"
: "=r" (zero)
);
__asm__ volatile (
"addq $1, %0"
: "=r" (one)
);
printf("value of zero, one, infinity = %llu, …Run Code Online (Sandbox Code Playgroud)