繁体   English   中英

程序集打印变量和值

[英]Assembly print variables and values

我有这个代码

global start

section .text

start:
mov rax,0x2000004
mov rdi,1
mov rsi,msg
mov rdx,msg.len
syscall

mov rax,0x2000004
mov rdi,2
mov rsi,msgt
mov rdx,msgt.len
syscall

mov rax,0x2000004
mov rdi,3
mov rsi,msgtn
mov rdx,msgtn.len
syscall

mov rax,0x2000001
mov rdi,0
syscall

section .data

msg: db "This is a string",10
.len: equ $ - msg

var: db 1

msgt: db "output of 1+1: "
.len: equ $ - msgt

msgtn: db 1
.len: equ $ - msg

我想打印变量msgtn 我尝试了msgt: db "output of 1+1", var但是NASM汇编器失败:

second.s:35: error: Mach-O 64-bit format does not support 32-bit absolute addresses

除了变量之外,我还尝试了"output of 1+1", [1+1] ,但是得到了:

second.s:35: error: expression syntax error

我也尝试了无括号的操作,没有数字,只有字符串“ 1 + 1”。

我用来汇编程序的命令是:

/usr/local/Cellar/nasm/*/bin/nasm -f macho64 second.s && ld -macosx_version_min 10.7.0 second.o second.o

nasm -v显示:

NASM version 2.11.08 compiled on Nov 27 2015

带有Intel Core i5的OS X 10.9.5(x86_64组件)

db指令使您可以将汇编时间常数字节放入目标文件中(通常在数据部分中)。 您可以使用表达式作为参数,以使汇编器在汇编时为您做一些数学运算。 在运行时发生的任何事情都需要由您编写并得到运行的指令来完成。 不同于C ++,全局变量可以有一个在后台启动时运行的构造函数。


msgt: db "output of 1+1", var

将放置这些ascii字符,后跟(?的低字节) var的绝对地址。 您将使用这种方法(使用dddq )来执行类似C的操作: int var; int *global_ptr = &var; int var; int *global_ptr = &var; ,其中有一个全局/静态指针变量,该变量最初已初始化为指向另一个全局/静态变量。 我不确定MacOS X是否允许使用64位指针,还是只是拒绝对32位地址进行重定位。 但这就是为什么您得到:

second.s:35: error: Mach-O 64-bit format does not support 32-bit absolute addresses

请注意,指针的数值取决于代码在虚拟地址空间中的加载位置。 因此,地址严格来说不是汇编时间常数。 linker需要标记的东西,需要运行时搬迁,像你这样的64位立即常数地址mov到寄存器( mov rsi,msg )。 有关地址与lea rsi, [rel msg]之间的区别的某些信息,请参见此答案 ,以使用相对RIP方法将地址保存到寄存器中。 (该答案具有指向更详细信息的链接, Wiki也是如此)。


您尝试使用db [1+1] :您期望什么? NASM语法中的[]表示内存引用。 首先 :结果字节必须是一个汇编时间常数。 我不确定是否有简单的语法可以复制其他地址的内容,但这不是。 (我只是定义一个宏,并在两个地方都使用它。) 第二2不是有效地址。


msgt: db "output of 1+1: ",   '0' + 1 + 1,    10

将在目标文件中的该点放置ASCII字符: output of 1+1: 2\\n 10是ASCII换行符的十进制值。 '0'是写入0x30的一种方式,ASCII编码字符'0' 2字节不是可打印的ASCII字符。 你的版本,这样做会打印的2有个字节,但你不会注意到,除非你的管道输出到hexdump (或od -t x1c什么,IDK什么OS X提供。 od是不是很漂亮,但它广泛可用。)

请注意,此字符串不是以空值结尾的。 如果您想将其传递给期望使用隐式长度字符串的内容(例如fputs(3)strchr(3) ,而不是write(2)memchr(3) ),请加上额外的, 0以添加零,个字节之后。


如果要在运行时进行数学运算,则需要将数据存入寄存器,将其添加,然后将数字的字符串表示形式存储到某个地方的缓冲区中。 (或者一次打印一个字节,但这太可怕了。)

简单的方法是只调用printf ,以轻松地打印出替换了某些内容的常量字符串。花时间编写需要手工调整的代码部分的asm,而不是重新实现库函数。

在注释中有一些关于从字符串到整数的讨论。


您的链接命令看起来很有趣:

ld -macosx_version_min 10.7.0 second.o second.o

您确定要两次相同的.o吗?


你可以节省一些代码仅字节mov荷兰国际集团,以32位的寄存器时,你不需要符号扩展到64位REG。 例如,用mov edi,2代替mov rdi,2保存一个字节(REX前缀),除非NASM很聪明并且无论如何都要这样做(实际上,确实如此)。

lea rsi, [rel msg] (或使用default rel )是一条比mov r64, imm64短的指令。 (AT&T助记符是movabs ,但Intel语法仍称其为mov 。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM