我写了下面的汇编代码,它可以直接通过as和ld构建pass。
as cpuid.s -o cpuid.o
ld cpuid.o -o cpuid
Run Code Online (Sandbox Code Playgroud)
但是当我使用gcc来完成整个过程时。我遇到以下错误。
$ gcc cpuid.s -o cpuid
/tmp/cctNMsIU.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cctNMsIU.o: relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
然后我将 _start 修改为 main,并将 -fPIC 添加到 gcc 参数。但这并不能解决我的 ld 错误。错误消息更改为以下。
$ gcc …Run Code Online (Sandbox Code Playgroud) 考虑这个 AMD64 汇编程序:
.globl _start
_start:
xorl %edi, %edi
movl $60, %eax
syscall
Run Code Online (Sandbox Code Playgroud)
如果我编译gcc -nostdlib并运行ldd a.out,我得到这个:
statically linked
Run Code Online (Sandbox Code Playgroud)
如果我改为使用gcc -static -nostdlib并运行编译它ldd a.out,我会得到这个:
not a dynamic executable
Run Code Online (Sandbox Code Playgroud)
什么之间的区别statically linked和not a dynamic executable?如果我的二进制文件已经静态链接,为什么添加-static会影响任何事情?
我正在尝试在ASM中创建一个共享库(*.so),我不确定我是否正确...
我的代码是:
.section .data
.globl var1
var1:
.quad 0x012345
.section .text
.globl func1
func1:
xor %rax, %rax
# mov var1, %rcx # this is commented
ret
Run Code Online (Sandbox Code Playgroud)
要编译它我运行
gcc ker.s -g -fPIC -m64 -o ker.o
gcc ker.o -shared -fPIC -m64 -o libker.so
Run Code Online (Sandbox Code Playgroud)
我可以访问变量var1并使用dlopen()和dlsym()从C中的程序调用func1.
问题在于变量var1.当我尝试从func1访问它时,即取消注释该行,编译器会生成错误:
/usr/bin/ld: ker.o: relocation R_X86_64_32S against `var1' can not be used when making a shared object; recompile with -fPIC
ker.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
我不明白.我已经用-fPIC编译了,那有什么不对?
什么是callx86机器代码中绝对指针的"正确"方法?有没有一种方法可以在一条指令中完成它?
我想做什么:
我正在尝试基于"子程序线程"构建一种简化的迷你JIT(仍然).它基本上是字节码解释器中最短的步骤:每个操作码都是作为一个单独的函数实现的,因此每个基本的字节码块都可以"JIT"到它自己的新程序中,如下所示:
{prologue}
call {opcode procedure 1}
call {opcode procedure 2}
call {opcode procedure 3}
...etc
{epilogue}
Run Code Online (Sandbox Code Playgroud)
因此,我们的想法是每个块的实际机器代码只能从模板中粘贴(根据需要扩展中间部分),并且需要"动态"处理的唯一位是将每个操作码的函数指针复制到正确的位置作为每个调用指令的一部分.
我遇到的问题是了解call ...模板部分的用途.x86似乎没有考虑到这种用法,并且有利于相对和间接调用.
它看起来像我可以使用FF 15 EFBEADDE或2E FF 15 EFBEADDE在假设调用函数DEADBEEF(通过把东西变成一个汇编和反汇编,看到什么产生有效的结果,基本上发现了这些未通过了解他们在做什么),但我不理解的东东细分,特权和相关信息足以看出差异,或者这些信息与更常见的call指令有何不同.英特尔架构手册还建议这些仅在32位模式下有效,在64位模式下"无效".
有人可以解释这些操作码以及我是如何或者是否会为此目的使用它们或其他人?
(通过寄存器使用间接调用也有明显的答案,但这似乎是"错误的"方法 - 假设实际存在直接调用指令.)
I have a function foo written in assembly and compiled with yasm and GCC on Linux (Ubuntu) 64-bit. It simply prints a message to stdout using puts(), here is how it looks:
bits 64
extern puts
global foo
section .data
message:
db 'foo() called', 0
section .text
foo:
push rbp
mov rbp, rsp
lea rdi, [rel message]
call puts
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
It is called by a C program compiled with GCC:
extern void foo();
int main() {
foo(); …Run Code Online (Sandbox Code Playgroud) 我有一个用户程序,通常编译为有一个入口点0x400460,我必须重新定位,以便2GB在Linux中加载的共享库中有一个入口点.例如linux-vdso.so.1 => (0x00007fff109cd000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd195e6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcd199af000)
我使用gcc命令行参数-Wl,-Ttext=0x80000000来指定.textsegemnt 的起始地址.
问题是当我2GB在这个参数中给出一个上面的地址时,我得到一个链接器错误,它是:
gcc test.c -ggdb -Wl,-Ttext=0x80000000 -o test1
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 11
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 10
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 …Run Code Online (Sandbox Code Playgroud) 我试图跟进这个线程,遗憾的是它并没有完全解决我的问题.我试图运行的代码如下:
; File hello.asm
section .data
msg: db "Hello World!",0x0a,0
section .text
global main
extern printf
main:
push rbp
mov rbp, rsp
lea rdi, [msg] ; parameter 1 for printf
xor eax, eax ; 0 floating point parameter
call printf
xor eax, eax ; returns 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
我的系统是debian stretch:
$ uname -a
Linux <host> 4.8.0-1-amd64 #1 SMP Debian 4.8.7-1 (2016-11-13) x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
我使用yasm汇编程序如下:
$ yasm -f elf64 -g dwarf2 hello.asm
Run Code Online (Sandbox Code Playgroud)
因为我在上面的源代码中的入口点是main最后的ret …
好吧,据我所知ET_EXEC用于表示该文件是可执行文件,而ET_DYN表示该文件是一个共享库。所以可以肯定的是,我用 C 编写了一个简单的程序,但问题是readelf -h产生了以下内容:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
.
.
.
Run Code Online (Sandbox Code Playgroud)
我认为这与我使用的编译器有关,所以我对/bin 中的一些实用程序做了同样的事情,但不幸的是得到了相同的结果。那么问题来了:为什么 readelf 将可执行文件识别为共享库?
我正在尝试生成最小的 C 程序,以查看通过运行它执行了多少指令。我禁用了库的使用并禁用了 vdso。然而,我的 C 程序(gdb 说是 7 条汇编指令)根据 perf stat 最终执行了 17k 条指令。
这是正常数量的指令只是为了设置程序吗?根据 gdb,来自 ld-linux-x86-64.so.2 的代码被映射到程序地址空间。鉴于我禁用了 vdso 并且不包含任何库,此文件是否需要运行该程序?这可能是 17k 指令的原因吗?
我的 C 程序foo5.c
int main(){
char* str = "Hello World";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我如何编译:
gcc -nostdlib -nodefaultlibs stubstart.S -o foo5 foo5.c
Run Code Online (Sandbox Code Playgroud)
stubstart.S
.globl _start
_start:call main;
movl $1, %eax;
xorl %ebx, %ebx;
int $0x80
Run Code Online (Sandbox Code Playgroud)
性能统计输出:
Performance counter stats for './foo5':
0.60 msec task-clock:u # 0.015 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 …Run Code Online (Sandbox Code Playgroud) 使用以下命令在我的Mac计算机上运行此代码:
nasm -f macho64 -o max.a maximum.asm
Run Code Online (Sandbox Code Playgroud)
这是我尝试在计算机上运行的代码,该代码在数组中找到最大的数字。
section .data
data_items:
dd 3,67,34,222,45,75,54,34,44,33,22,11,66,0
section .text
global _start
_start:
mov edi, 0
mov eax, [data_items + edi*4]
mov ebx, eax
start_loop:
cmp eax, 0
je loop_exit
inc edi
mov eax, [data_items + edi*4]
cmp eax, ebx
jle start_loop
mov ebx, eax
jmp start_loop
loop_exit:
mov eax, 1
int 0x80
Run Code Online (Sandbox Code Playgroud)
错误:
maximum.asm:14: error: Mach-O 64-bit format does not support 32-bit absolute addresses
maximum.asm:21: error: Mach-O 64-bit format does not support 32-bit absolute …Run Code Online (Sandbox Code Playgroud)