首页 > 解决方案 > TASM 初始化局部变量

问题描述

我是汇编语言的新手,我正在使用 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]
    LEA 输出

    MOV DX, OFFSET a
    移动输出

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

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

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

标签: assemblyx86-16tasmemu8086dosbox

解决方案


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',因为它是在 asm-timeLOCAL a[12]: BYTE定义的 TASM 方式。aBP-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但本地堆栈变量的默认段寄存器BPSS(而不是DS)。幸运的是,在您的程序中DS=SS,但在非小内存模型中并非总是如此。


推荐阅读