You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在汇编中修改保留字节数?附相关代码咨询

关于汇编中动态调整预留字节数的问题

核心结论

运行时无法修改.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:

  1. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:22:31