assembly - NASM - 将一个变量的地址存储在另一个变量中
问题描述
我目前正在学习汇编。我想编写一个程序,它以三个相互指向的变量结束:
0x804a000: 0x804a001 ; 0 -> 1
0x804a001: 0x804a002 ; 1 -> 2
0x804a002: 0x804a000 ; 2 -> 0
根据 其他一些帖子,我可以 检索(例如 for ): mov
- 变量的内容
x
使用[x]
- 变量的地址
x
使用x
这是我到目前为止提出的:
section .bss
head resd 3 ; reserve three dwords
section .text
global _start
_start:
xor eax, eax
xor ebx, ebx
xor ecx, ecx ; counter = 0
mov eax, head ; move the address of head into eax: eax -> 0
mov ebx, eax ; move the address of head from eax into ebx: ebx -> 0
add ebx, 2 ; ebx -> 2
mov [ebx], eax ; move the value of eax ( = the address of 0 ) into the address in ebx ( = the address of 2)
loop: ; first run second run
inc ecx ; eax -> 0 eax -> 1
mov ebx, eax ; ebx -> 0 ebx -> 1
add eax, 1 ; eax -> 1 eax -> 2
mov [ebx], eax ; 0 -> 1 1 -> 2
cmp ecx, 2 ; ecx = 1 < 2 ecx = 2 == 2
jl loop
mov eax, head ; eax points to the first element
mov eax,1 ; system call number (sys_exit)
int 0x80 ; call kernel
这应该基本上是0。保留三个dword,其中第一个在地址head
- 将 0 的地址装入
eax
, 将 2 的地址装入ebx
mov [ebx], eax
将 0 的地址写入 2 (2 -> 0
)- 对字段 0 和 1 重复相同的操作
0 -> 1
:1 -> 2
- 将head的地址存入eax
现在我组装并运行整个事情
nasm -f elf -g -F dwarf test.asm
ld -m elf_i386 -o test.out test.o
但是, 和 中的值0
都是2
错误的,因为我可以使用以下方法进行检查gdb
:
gdb test.out
(gdb) b 27 // break after mov eax, head
(gdb) r
(gdb) i r eax
eax 0x804a000 134520832 // eax points to head
(gdb) print *134520832
$1 = 77595137 // cell 0 does not point to cell 1
(gdb) print *134520833
$2 = 134520834 // cell 1 does point to cell 2
(gdb) print *134520834
$3 = 134743200 // cell 2 does not point to cell 1
这些错误的价值观从何而来?
也许这是因为我尝试将整个 32 位eax
写入 16 位双字?我尝试将线条更改为mov [ebx], ax
但最终得到相同的结果。
我能想出的另一个原因是内存地址大于 a dword
,所以我尝试使用qword
s 代替,但最终得到了另一个错误的结果。
我还尝试使用lea assembly instructionlea
中所建议的指令,这会导致相同的结果。
有人可以帮我弄这个吗?提前致谢
解决方案
一个 dword 在 x86 中是 32 位的,所以是 4 个字节。“双字”,其中“字”是 16 位的(因为 x86 是从 16 位 8086 演变而来的)。是的,正如您所发现的,x86 是字节可寻址的,就像所有现代主流 ISA 一样。
此外,您的标题问题的答案将是mov dword [head], head+4
例如。 head+4
在汇编+链接时计算,并变成一个 32 位立即操作数保存该地址,而head
变成一个 32 位位移保存另一个地址。
或者您可以像您正在做的那样使用循环,但简化mov [eax-4], eax
为将当前元素的地址存储到前一个元素中,并add eax,4
推进指针。无需复制到 EBX,只需对内存操作数使用寻址模式以获得恒定偏移量。
如果您想要整个循环/函数的完整示例,请用 C 语言编写并查看编译器输出。如何从 GCC/clang 程序集输出中删除“噪音”?
推荐阅读
- javascript - 在 linux 上安装 typeorm 后得到“bash: typeorm: command not found”
- java - 导入 org.springframework.security 无法解决
- python - ValueError:变量的初始化程序来自控制流构造内部,例如循环或条件。使用 lambda 作为初始化器
- javascript - ReactJS 两种方式绑定不起作用,绑定有问题
- html - 如何在我的 Django 应用程序中为我的图像添加动画?
- python - 在 Python 中,'a' > 'A' 为真的过程和重要性是什么?
- r - 如何在基于 R 中的行业代码的面板线性模型 (plm) 中包含行业固定效应
- jenkins-pipeline - 在不同的 slave 上并行执行 Jenkins 流水线的阶段
- c# - Math.Truncate 的问题,将双精度数转换为整数
- postgresql - CrashLoopBackOff (postgres) - GCP