【问题标题】:Running X86 Assembly on Win8 64 bit在 Win8 64 位上运行 X86 程序集
【发布时间】:2015-03-12 17:41:37
【问题描述】:

我是组装新手,我正在尝试创建复制笛卡尔的叶 (x^3 + y^3 - 3*axy = 0 其中 a=12)。我已经完成了代码,当我编译和链接时,我没有收到任何错误。我在 64 位 win8 上通过 DOSBox 0.74 使用 TASM。但是当我尝试通过 DOSBox 执行 folium.exe 文件时,我得到一行随机字符,它说无法在随机字符的中心打开文件。我不知道为什么会这样,根据我的代码它应该显示“0”或“”。要么我组装错误,要么我的代码中有我不知道的错误。

在 DOSBox 0.74 中,我只需输入TASM folium.asm,然后输入LINK folium,然后输入folium 即可执行。这就是我为我的其他代码所做的方式并且它有效。

title   folium.asm  ; draws the loop in a cubic curve called the folium of Descartes, defined by x^3 + y^3 - 3*a*x*y = 0, where a = 12
    .model  small
    .stack  100h

    .data
    include const.inc

x   dw  ?
y   dw  ?
z   dw  ?

    .code

main    proc

; initialize DS
    mov ax, @data
    mov ds, ax

; y := 0;
    mov y, 0

while01: ; y <= 20
    cmp y, 20
    jnle    endwhile01

; do01
; x := 0
    mov x, 0

while02: ; x <= 20
    cmp x, 20
    jnle    endwhile02

; do01
; z := x*x*x + y*y*y - 36*x*6
    mov ax, x
    imul x
    imul x
    mov z, ax
    mov ax, y
    imul y
    imul y
    add z, ax
    mov ax, 36
    imul x
    mov bx, ax
    mov ax, 6
    imul bx
    sub z, ax

; if01 z <= 0
    cmp x, 0
    jnle    else01

then01:
; write '0'
    mov ah, dispstr
    mov dx, offset '0'
    int dosfunc
    jmp endif01

else01:
; write ' '
    mov ah, dispstr
    mov dx, offset ' '
    int dosfunc

endif01:
; x := x + 1;
    inc x
    jmp while02

endwhile02:
; write cr, lf
    mov ah, wrchr
    mov dl, cr
    int dosfunc
    mov dl, lf
    int dosfunc 

; y := y + 1
    inc y
    jmp while01

endwhile01:

; return -- to DOS
    mov ah, ret2dos
    int dosfunc
main    endp
    end main

【问题讨论】:

  • 你能显示dosfuncwrchrdispstr的值是什么吗?在您的int dosfunc ; mov dl, lf ; int dosfunc 中,您可能应该在第二个int dosfunc 之前重新加载mov ah, wrchr,因为尚不清楚int dosfunc 在执行时是否会保留ah 的值。 dispstr 是否设置为 09h?如果是,则ds:dx 需要指向内存中以美元符号终止的字符串 ($)。我认为offset '0'offset ' ' 不会在那里工作。您将从内存中这些位置的任何内容中获得一些非常奇怪的输出。

标签: assembly dos tasm


【解决方案1】:

mov dx, offset '0'mov dx, offset ' ' 不要 生成字符串或字符串的偏移量。 TASM 仅将 '0' 替换为 ASCII 代码 (30h),因此指令将为 mov dx, 30h 并且在 DS:0030h 处不是 '0'。

我不知道const.inc。我猜有这样的定义:

dosfunc = 21h
ret2dos = 4Ch
dispstr = 09h
wrchr = 02h
cr = 0Dh
lf = 0Ah

MSDOS 函数 Int 21h / AH=09h (mov ah, dispstr; int dosfunc) 期望在 DX 中偏移到以“$”结尾的 ASCII 字符串。不要忘记'$',否则输出不会停止!

插入.data 部分:

zero db '0$'
space db ' $'

改变

mov dx, offset '0'

mov dx, offset zero

mov dx, offset ' '

mov dx, offset space

【讨论】:

  • 谢谢你的工作。我没有被教导 const.ini 中的内容或 dispstr 如何工作,只是如何使用它们来显示字符串。所以非常感谢你,下次我会记住这一点。
【解决方案2】:

如果dispstr 是DOS 函数09h,那么它需要指向内存中字符串的指针,该字符串以美元符号($) 终止。您不能只将offset ' 'offset '0' 加载到dx 中,因为x86 程序集不会隐式生成指向字符串的地址。相反,它将采用' ''0' 的ASCII 值并将其加载为地址,该地址指向内存中某个奇怪的位置,因此您会看到奇怪的输出。

如果你想打印单个字符,你应该使用DOS函数02h

mov ah, wrchr
mov dl, '0'
int dosfunc

这个序列看起来也很可疑。不清楚DOS中断21h是否会保留ah的值:

mov ah, wrchr
mov dl, cr
int dosfunc
mov dl, lf
int dosfunc 

所以重新加载会更安全:

mov ah, wrchr
mov dl, cr
int dosfunc
mov ah, wrchr
mov dl, lf
int dosfunc 

【讨论】:

    猜你喜欢
    • 2018-10-15
    • 2015-04-03
    • 2012-03-11
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2015-09-03
    相关资源
    最近更新 更多