如何在汇编中修改保留字节数?附相关代码咨询
关于汇编中动态调整预留字节数的问题
核心结论
运行时无法修改.bss段中预留的字节数量。
原因解释
.bss段的内存大小是在汇编、链接阶段就确定的——链接器会根据你代码里的resb size这类伪指令,在程序加载到内存时分配固定大小的空间。程序运行后,内存布局已经固定,没法再调整.bss里预留的内存大小。你的calculateBytes是在运行时计算所需字节数,但这时候output的内存空间早就分配好了,没法改变它的预留大小。
替代方案
方案1:编译时静态计算准确大小(推荐,适合max是常量的场景)
因为你的max是用equ定义的常量,完全可以用数学公式在编译时算出所需的准确字节数,不需要运行时计算:
- 三角形的
*总数量:max*(max+1)/2(等差数列求和) - 加上
max个换行符(每行末尾一个),总字节数是:max*(max+1)/2 + max = max*(max+3)/2
修改代码里的size定义即可:
section .bss max equ 30 size equ (max*(max+3))/2 ; 编译时直接算出准确值 output resb size
这样.bss段只会预留刚好够用的内存,不会浪费空间。
方案2:运行时动态分配内存(适合max是运行时变量的场景)
如果max是程序运行时才能确定的值(比如从用户输入读取),可以用Linux系统调用动态申请内存,常用的有brk或mmap:
- 用brk分配内存:
- 先调用
brk(0)获取当前堆的起始地址(break指针) - 计算所需字节数后,将break指针加上该数值,再次调用
brk完成分配 - 用这块动态分配的内存存储输出内容,程序退出时系统会自动回收内存
- 先调用
示例代码片段(替换原.bss的output部分):
_start: ; 先计算所需字节数(你的calculateBytes逻辑) mov r8, max mov r10, r8 mov r11, r8 calculateBytes: add r11, r10 dec r10 jnz calculateBytes ; 现在r11是总字节数 ; 调用brk获取当前break地址 mov rax, 12 ; brk系统调用号 xor rdi, rdi syscall mov rsi, rax ; rsi保存堆起始地址(即动态分配的output指针) ; 计算新的break地址:当前break + 总字节数 add rax, r11 mov rdi, rax mov rax, 12 syscall ; 现在rsi指向的就是分配好的内存 ; 后续生成三角形的逻辑,把原代码里的rdx初始值改成rsi即可 mov rdx, rsi ; ... 剩下的line、lineDone逻辑不变 done: ; 写stdout时,rsi是动态分配的内存,rdx是r11(总字节数) mov rax, 1 mov rdi, 1 ; rsi已经是动态内存地址 mov rdx, r11 syscall ; ... 退出逻辑不变
对你现有代码的补充说明
你的calculateBytes逻辑其实是对的,最终r11的值刚好是总字节数(*的数量+换行符数量),但问题在于这个值没法用来修改已经固定的.bss内存大小,所以只能用上面的替代方案解决。
内容的提问来源于stack exchange,提问作者12944qwerty
相关产品推荐
相关产品推荐

