【问题标题】:Simplify assembly program简化装配程序
【发布时间】:2015-11-17 09:30:12
【问题描述】:

我目前有这个代码:

.model small
.stack 100h
.data
.code
    CLRSCR:
        mov ax,0003h
        int 10h
    ROWCOLINIT:
        mov dh,0
        mov dl,0
    MYLOOP:
        mov ax,dx
        mov ah,0
        mov bl,2
        div bl
        cmp ah,0
        je EVENCOL
    ODDCOL:
        mov al,2
    CURSORINIT:
        mov ah,02h
        mov bh,0
        int 10h
    ATTRIBINIT:
        mov ah,09h
        mov bl,30h
    PRINTCHAR:
        mov cx,1
        int 10h
        inc dl
        cmp dl,5
        je RESETCOLINCROW2
    DONTRESETCOL:
        cmp dh,5
        je EXIT
        jmp MYLOOP
    LOOP2:
        mov ax,dx
        mov ah,0
        mov bl,2
        div bl
        cmp ah,0
        je EVENCOL2
    ODDCOL2:
        mov al,42
    CURSORINIT2:
        mov ah,02h
        mov bh,0
        int 10h
    ATTRIBINIT2:
        mov ah,09h
        mov bl,30h
    PRINTCHAR2:
        mov cx,1
        int 10h
        inc dl
        cmp dl,5
        je RESETCOLINCROW
    DONTRESETCOL2:
        cmp dh,5
        je EXIT
        jmp LOOP2   
    EXIT:
        mov ah,4ch
        int 21h
    RESETCOLINCROW:
        mov dl,0
        inc dh
        jmp DONTRESETCOL
    RESETCOLINCROW2:
        mov dl,0
        inc dh
        jmp DONTRESETCOL2
    EVENCOL:
        mov al,42
        jmp CURSORINIT
    EVENCOL2:
        mov al,2
        jmp CURSORINIT2

end

我的程序输出是:

*☻*☻*
☻*☻*☻
*☻*☻*
☻*☻*☻
*☻*☻*

我正在尝试使用 2 个循环来简化此代码。如何在汇编程序中进行嵌套循环?

【问题讨论】:

  • 规范是否允许您更改为另一种语言? :)
  • 也许你应该评论你的代码并告诉我们这个程序应该做什么?
  • 虽然你说要简化为两个循环,但也可以用一个循环产生想要的效果(单循环也更简单)
  • 其实可以是一个循环。如果您不将输出包装成几行,那么它是一个微笑星-微笑-星-...字符流。编写一个循环,在每个奇数迭代中打印一个星形,在每个偶数迭代中打印一个微笑(使用“test total_char_count, 1”来确定当前迭代是奇数还是偶数)。然后,如果已打印的字符模块 5 的总数为零,则将“if”(cmp/check)放入打印换行符的循环中。以某种方式检测打印字符数何时等于(列 X 行)并退出循环。
  • 你根本不需要循环。您可以通过单个 BIOS 调用显示该输出。

标签: assembly nested-loops dos masm x86-16


【解决方案1】:

这是一种解决方案,仅使用 8086/8088 指令。它不依赖于 386 指令,因此应该在任何 8086/8088+ 模拟器中运行。

这个程序的想法是我们在 * 和笑脸 (02h) 之间交替打印 25 个字符。我们每行打印 5 个字符(在每个字符后面移动光标),如果我们打印了 5 个字符,则跳到下一行的开头。我们这样做,直到我们打印出所需的字符数(25)。

为了在 * 和笑脸之间交替,我使用了这样一个事实,即我想要的字符取决于我正在处理的当前字符(在 DI 中)是奇数还是偶数。如果是偶数,我会打印一个 *,如果是奇数,我会打印一个笑脸。

我在代码中提供了 cmets,以便了解每一步发生的情况。我将这些寄存器用作变量。

BP = Num of characters per row 
DI = Current character number we are processing  
BH = Current text page to print on 
BL = Attribute to use when printing to screen 
CX = Total number of characters to print with int 10h/ah=09h. Always = 1
DH = Current cursor row
DL = Current cursor column

我使用的代码是:

.model small
.stack 100h

.data
outcharsarr db '*', 2    ; even = *  odd = smiley face

CHARSPERROW  equ 5       ; Number of characters to print per row
CHARSTOPRINT equ 25      ; Total number of characters to print

.code
    MAIN:
    mov ax, @data        ; Use the proper data segment
    mov ds, ax

    mov ax,0003h         ; Clear screen
    int 10h

    xor   dx, dx         ; Update cursor to 0,0 . DH=Row, DL=Column
    mov   ah, 2          
    int   10h

    mov   bp, CHARSPERROW; BP = Num of characters per row
    xor   di, di         ; DI = Current character number we are processing
    mov   bx, 0030h      ; BH = Current page to print on
                         ; BL = Attribute to use when printing
    mov   cx, 1          ; CX = Number of characters to print

printloop:
    xor   si, si         ; Index to even/odd array
    test  di, 1          ; Is current character pos even/odd?
    jz    pl_evenpos     ; if even si=0
    inc   si             ; if odd  si=1
pl_evenpos:    
    mov   al, outcharsarr[si] 
                         ;Print the character out based on even/odd index
    mov   ah, 09h
    int   10h

    dec   bp             ; dec number of chars still needed on current row
    ja    pl_nextcol     ; If we haven't printed enough for current row 
                         ; goto next column

    ; If we reach here we have printed the require number for this row
    ; advance to beginning of next row
    xor   dl, dl         ; col=0
    inc   dh             ; row=row+1
    mov   ah, 2          ; Update cursor
    int   10h
    mov   bp, CHARSPERROW 
                         ; Reset the number of characters needed on current row 
    jmp   pl_endloop

pl_nextcol:
    inc   dl             ; col=col+1
    mov   ah, 2          ; Update cursor
    int   10h

pl_endloop:
    inc   di
    cmp   di, CHARSTOPRINT
                         ; Have we reached total number of characters to print?
    jb    printloop      ;    If not got back and continue printing

    mov ah,4ch           ; Exit program
    int 21h

end MAIN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 2015-07-09
    相关资源
    最近更新 更多