【问题标题】:TASM Initializing Local VariablesTASM 初始化局部变量
【发布时间】:2021-03-17 12:01:13
【问题描述】:

我是汇编语言新手,我正在使用 DOSBOX x86-16 中的 TASM 进行编程

我在互联网上到处寻找初始化局部变量的 TASM 方法,但没有找到。
实际上,在那之前我的第一个问题是弄清楚如何在 TASM 中创建一个局部变量。
在没有找到一个专门用于 TASM 的之后,我尝试了一个用于 MASM 的,然后在 TASM 中尝试了它,令人惊讶的是它起作用了!

现在唯一的问题是我找不到初始化该局部变量的方法。 我想出了一个天真的解决方案,这是我的代码:

.model small
.stack 0100h
.data

.code
_MAIN PROC
    MOV AX, @DATA
    MOV DS, AX
        
    LOCAL a[12]: BYTE
    ; my solution to initializing the a[12] local variable
    MOV a[0], 'h'
    MOV a[1], 'a'
    MOV a[2], 'n'
    MOV a[3], 'l'
    MOV a[4], 'o'
    MOV a[5], '$'

    LEA DX, [a]  ; for some reason "MOV DX, OFFSET a" doesn't output "hanlo" in dosbox (i guess it points to a different address? I'm not sure how tho)
    MOV AH, 09h
    INT 21h
        
    ; EXIT
    MOV AH, 4Ch
    INT 21h
_MAIN ENDP
    
END _MAIN

问题

1.如何初始化这个局部变量?有没有办法可以做类似于初始化 .data 段中的变量的事情?像这样:
.model small
.stack 0100h
.data
    inputPrompt db "Enter your name: $" ; can i do something like this, but inside the .code segment?
.code
...
  1. 正如您在我的代码MOV DX, OFFSET a 的第二条注释中看到的那样,由于某种原因,它没有指向a 局部变量的开头。我将其更改为LEA DX, [a] 然后它突然起作用了。这是两个代码的输出:

    LEA DX, [a]


    MOV DX, OFFSET a


    您认为这里到底发生了什么?

  2. 我还在 EMU8086 中尝试了我的 TASM 代码,因为我可以清楚地看到正在设置的寄存器,而且它只是一个非常好的学习汇编的程序。但是由于某种原因,当我尝试这个确切的代码时,它在执行时会在 EMU8086 中出现错误,特别是在使用 LOCAL 指令时(很可能是因为 EMU8086 使用了不同的语法)。

    一切正常,除非我使用 LOCAL 指令。这是错误: 在 EMU8086 中声明和初始化局部变量的正确语法是什么?

最后,如果你们知道一个非常好的 x86-16 TASM DOSBOX 汇编教程,请分享,它解释了这个和那个寄存器的确切作用(我猜这完美地解释了基本原理)

【问题讨论】:

  • TASM 和 EMU8086 是不同的汇编程序。它们对实际指令和一些基本指令使用相同的语法,但是像 local 指令这样的额外奇怪的东西显然是 TASM 独有的。通常,您只需使用sub sp, 12 或其他方式手动执行此操作。在 asm 中使用复杂的“高级”功能通常会破坏学习 asm 的目的;我建议您仅在熟悉 asm 并知道如何查看反汇编输出以查看 TASM 为这些指令生成的实际指令后才检查这些功能。
  • OFFSET 不是运行时运算符。像OFFSET a 这样的表达式的值是在汇编或链接时计算的。但是使用局部变量是不可能的,因为这样的变量在你进入函数时在堆栈上分配,然后在你离开函数时释放。
  • 我明白了,谢谢伙计们,我会阅读更多关于堆栈的信息,我实际上是在将函数帧保存在堆栈中之前通过将它们推入堆栈来保存所有寄存器先前状态的内容当函数结束时,它将通过将其弹出来恢复先前的状态,但在不同的上下文中。如果你们知道任何很好的 16 位 asm 教程可以很好地解释这些概念,请分享。

标签: assembly x86-16 tasm emu8086 dosbox


【解决方案1】:

TASM chess3.asm, chess3.obj, chess3.lst 给出列表文件chess33.lst

  1 0000                         .model small
  2 0000                         .stack 0100h
  3 0000                         .data
  4
  5 0000                         .code
  6 0000                         _MAIN PROC
  7 0000  B8 0000s                   MOV AX, @DATA
  8 0003  8E D8                      MOV DS, AX
  9
 10                                  LOCAL a[12]: BYTE
 11                                  ; my solution to initializing the a[12] local variable
 12 0005  C6 46 F4 68                MOV a[0], 'h'
 13 0009  C6 46 F5 61                MOV a[1], 'a'
 14 000D  C6 46 F6 6E                MOV a[2], 'n'
 15 0011  C6 46 F7 6C                MOV a[3], 'l'
 16 0015  C6 46 F8 6F                MOV a[4], 'o'
 17 0019  C6 46 F9 24                MOV a[5], '$'
 18
 19 001D  8D 56 F4                   LEA DX, [a]  ; for some reason "MOV DX, OFFSET a" doesn't output "hanlo" in dosbox (i guess+
 20                              it points to a different address? I'm not sure how tho)
 21 0020  B4 09                      MOV AH, 09h
 22 0022  CD 21                      INT 21h
 23
 24                                  ; EXIT
 25 0024  B4 4C                      MOV AH, 4Ch
 26 0026  CD 21                      INT 21h
 27 0028                         _MAIN ENDP
 28
 29                              END _MAIN

指令MOV a[0],'h'组装成C6 46 F4 68实际上是伪装的MOV BYTE [BP-12+0],'h',因为LOCAL a[12]: BYTE是TASM在asm时将a定义为BP-12的方式。

LEA DX,[a] 组装为LEA DX,[BP-12]。这就是MOV DX,OFFSET a 不汇编的原因:MOV DX,OFFSET BP-12 是无效指令。

还要注意 DOS 函数 http://www.ctyme.com/intr/rb-2562.htm :它需要 DS:DX 中的字符串地址,但使用 BP 寻址的本地堆栈变量的默认段寄存器是 SS(而不是 DS)。幸运的是,在您的程序中 DS=SS,但在非小内存模型中并非总是如此。

【讨论】:

  • 谢谢,很清楚。我有一个关于如何解释列表文件输出的问题。我认为第一列只是第二行的行号,我猜是偏移量,但是这个偏移量在哪个段?第三个我认为代码的十六进制版本,我可以理解被转换为其十六进制 ascii 的立即值(例如'$'-> 24)。但我不明白剩余的 asm 到十六进制的转换。例如 MOV a[5], '$' 转换为 C6 46 F9 24 (我从 $ 知道 24,但其余的我不确定)。你知道这个转换是如何工作的吗?最后 4th 只是原始源代码
  • C6 46 F9 24 是汇编指令`MOV BYTE [BP-12+5],'$'`。是的,您很好地解释了列表列。第二列中的偏移量属于哪个段是一个很好的问题,您必须查找更改当前段的语句并记住它们。或者使用其他一些将当前段标记为偏移列的汇编器,如euroasm.localhost/eatests/t2481.htm
猜你喜欢
  • 1970-01-01
  • 2016-09-07
  • 2012-10-03
  • 2017-05-14
  • 2016-01-14
  • 1970-01-01
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多