【发布时间】:2020-06-29 08:42:22
【问题描述】:
我正在尝试学习汇编、编译器(LLVM)和升降器。
我可以只用 nasm 编写汇编代码。(如 this)
下面是我的汇编代码。
section .data
hello_string db "Hello World!", 0x0d, 0x0a
hello_string_len equ $ - hello_string
section .text
global _start
_start:
mov eax, 4 ; eax <- 4, syscall number (print) But, never execute.
mov ebx, 1 ; ebx <- 1, syscall argument1 (stdout) But, never execute.
mov ecx, hello_string ; ecx <- exit_string, syscall argument2 (string ptr) But, never execute.
mov edx, hello_string_len ; edx <- exit_string_len, syscall argument3 (string len) But, never execute.
int 0x80; ; syscall But, never execute.
mov eax, 1 ; eax <- 1, syscall number (exit) But, never execute.
mov ebx, 0 ; ebx <- 0, syscall argument1 (return value) But, never execute.
int 0x80; syscall But, never execute.
;nasm -felf32 hello.x86.s -o hello.o
;ld -m elf_i386 hello.o -o hello.out
然后我检查二进制文件。
在这里,我找不到函数。我同意 call 和 ret 指令是结合了一些指令的东西。
$readelf -s hello.o
Symbol table '.symtab' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS hello.x86.s
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 2
4: 00000000 0 NOTYPE LOCAL DEFAULT 1 hello_string
5: 0000000e 0 NOTYPE LOCAL DEFAULT ABS hello_string_len
6: 00000000 0 NOTYPE GLOBAL DEFAULT 2 _start
但是。如果我编译 c 程序并通过 readelf 检查该二进制文件。然后我可以找到“功能”。
附言
$readelf -s function.o | grep FUNC
3: 0000000000000000 18 FUNC GLOBAL DEFAULT 2 add
4: 0000000000000020 43 FUNC GLOBAL DEFAULT 2 main
在这里我可以看到什么是函数。
什么是函数不同的NOTYPE标签?
【问题讨论】:
-
对,汇编语言并没有真正的功能,只是实现该概念的工具(例如,在某处跳转和存储返回地址 = 调用,间接跳转到返回地址 = ret)。执行模型是纯粹的顺序和本地的,一次一条指令(在大多数 ISA 上,但有些 ISA 是 VLIW,例如一次执行 3 条,但在范围内仍然是本地的),每条指令都只是一个定义明确的指令更改为架构状态。你问的是这个吗?
-
您即将完成该课程。他们会教你。期望在一个 SO 问题中回答如此广泛的问题是非常荒谬的。
-
是的,C 编译器不会在函数之外放置任何指令。 (从技术上讲,间接调用
main的_start入口点不是一个函数;它不能返回并且必须进行exit系统调用,但这是用asm 编写的并且是libc 的一部分。它不是生成的由 C 编译器正确。) -
我可以在您的帖子中看到至少三个问题,并且没有一个问题有简单的是/否答案。
-
ELF 符号元数据可以由一些汇编器设置,例如在 NASM 中,
global main:function将符号类型标记为 FUNC。 (nasm.us/doc/nasmdoc8.html#section-8.9.5)。 GAS 语法等价物(C 编译器发出)是.type main, function。例如在godbolt.org 上添加一些代码并禁用过滤以在编译器输出中查看 asm 指令。但请注意,这只是链接器和调试器使用的元数据; CPU在执行时看不到这一点。这就是为什么没有人为 NASM 示例而烦恼的原因。
标签: assembly compiler-construction llvm-ir