操作或指令的参数大小非法 8086 子程序 [英] argument to operation or instruction has illegal size 8086 subroutine

查看:57
本文介绍了操作或指令的参数大小非法 8086 子程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始用微处理器8086的汇编程序编程.我尝试在屏幕上画一棵树,发送一个子程序,行,列,数量(从堆栈中收集),我出现的错误是

I started programming in assembler for microprocessor 8086. I try to draw a tree on the screen, sending a subroutine, row, column, amount (collected from the stack), the error I present is

操作或指令的参数大小非法

argument to operation or instruction has Illegal size

在第 21 行,即执行推送计数、列、行时.

on line 21, ie when performing the push count,column,row.

DATOS SEGMENT
row DB 1
colum DB 39
carac DB 2AH
count DB 1
ENDS
PILA SEGMENT STACK
    DB 100 DUP(?)
PILA ENDS
CODIGO SEGMENT
ASSUME CS:CODIGO , DS:DATOS,SS:PILA
INICIO :
    MOV AX,DATOS
    MOV DS,AX
    MOV AH,00h ;Clear 
    MOV AL,03h
    INT 10h

HACER : 

        PUSH   count ; LINE ERROR
        PUSH   colum ; LINE ERROR
        PUSH   row   ;LINE ERROR
        CALL DIBUJA ; CALL PROC DIBUJA
        DEC colum
        ADD count,2
        CMP colum ,0 ; LINE ERROR
        JAE HACER
        POP AX

FIN : MOV AH,4CH
      INT 21H

DIBUJA PROC 
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DX
    MOV BP,SP
    ADD BP ,8
    MOV DH, [BP]  ; ACCESS TO ROW
    ADD BP,2
    MOV DL,[BP]   ; ACCES TO COLUMN
    MOV AH,02H
    INT 10H
    MOV BH,0   ; PAGE
    MOV AL,2AH  ; CHAR * HEXADECIMAL
    MOV AH,0AH
    ADD BP,2  ; ACCES TO COUNT
    MOV CX, [BP] ; COUNT 
    INT 10H

    POP DX
    POP CX
    POP BX
    POP AX
    RET
DIBUJA ENDP

CODIGO ENDS
END INICIO

推荐答案

PUSH   count ; LINE ERROR
PUSH   colum ; LINE ERROR
PUSH   row   ;LINE ERROR

您会收到非法大小"错误,因为 push 指令无法处理字节大小的内存访问.一种解决方案是首先将字节大小的变量移动到 16 位通用寄存器的低字节中,然后将其压入.高字节将包含垃圾这一事实并不重要:

You get an "illegal size" error because the push instruction can't deal with a byte-sized memory access. A solution is to first move the byte sized variable in the low byte of a 16-bit general register and then push that. The fact that the high byte will contain garbage is of no importance:

mov  al, count
push ax
mov  al, colum
push ax
mov  al, row
push ax

<小时>

您的程序还有一些问题:


There are some more issues with your program:

  • BIOS SetCursor 函数还需要 BH 寄存器来包含您要为其设置光标的显示页面.将 mov bh,0 指令在程序中向上移动几行.
  • DIBUJA 过程推送了很多寄存器,但您忘记保留您使用的 BP 寄存器.
  • 设置 BP=8 可以访问返回地址,您希望在该地址访问参数.在您的代码中,您将在 [bp+10] 处找到第一个参数().
  • 每次调用该过程时,都会将一些值压入堆栈.返回时,您需要从堆栈中删除它们,否则堆栈溢出会损害您的程序.有两种方法可以解决这个问题:

  • The BIOS SetCursor function also requires the BH register to contain the display page for which you want to set the cursor. Move the mov bh,0 instruction a few lines up in your program.
  • The DIBUJA procedure pushes a lot of registers, yet you forget to preserve the BP register that you use.
  • Setting BP=8 gives access to the return address, where you want access to the arguments. In your code you'll find the 1st arg (row) at [bp+10].
  • Each time you call the procedure you push some values on the stack. Upon returning you need to remove these from the stack else a stack overflow will harm your program. There are 2 ways to solve this:

  • 让程序执行它的最后一条指令:

  • Have the procedure do it by writing as its last instruction:

ret 6

  • 调用返回后添加堆栈指针:

  • Add the stackpointer after returning from the call:

    call DIBUJA
    add  sp, 6
    

  • FIN 标签之前有一个多余的 pop ax.

    There's a superfluous pop ax right before the FIN label.

    当您编写 cmp colum, 0 jae HACER 时,您实际上编写了一个无限循环,因为变量中的每个值 colum 将始终高于或等于零.如果您将 colum 变量视为有符号量并使用有符号分支 jge HACER(跳转到大于或等于),您本可以摆脱它.

    When you wrote cmp colum, 0 jae HACER, you effectively wrote an infinite loop because every value in the variable colum will ALWAYS BE ABOVE OR EQUAL TO ZERO. You could have gotten away with it had you treated the colum variable a signed quantity and used the signed branch jge HACER (jump on greater or equal).

    HACER: 
        mov  al, count
        push ax
        mov  al, colum
        push ax
        mov  al, row
        push ax
        CALL DIBUJA
        inc  row          ; See final note!
        DEC  colum
        ADD  count, 2
        CMP  colum, 16    ; See final note!
        JAE  HACER
    FIN:
        MOV  AH,4Ch
        INT  21h
    
    DIBUJA PROC 
        PUSH AX
        PUSH BX
        PUSH CX
        PUSH DX
        push bp
        MOV  BP, SP
        MOV  DH, [BP+12]  ; ROW
        MOV  DL, [BP+14]  ; COLUMN
        MOV  BH, 0        ; PAGE
        MOV  AH, 02h
        INT  10h
        MOV  CX, [BP+16]  ; COUNT 
        MOV  AX, 0A2Ah    ; "*"
        INT  10h
        pop  bp
        POP  DX
        POP  CX
        POP  BX
        POP  AX
        RET  6            ; +6 to remove the 3 words that were pushed as arguments
    DIBUJA ENDP
    

    <小时>

    最后一点.

    要在 80x25 文本屏幕上获得下降树形状,您应该


    A final note.

    To obtain a descent tree shape on the 80x25 textscreen, you should

    • colum 达到 16 时停止主循环.低至 0 会用垃圾填满屏幕!
    • 增加 row 因为现在所有内容都显示在第 1 行上.
    • stop the main loop when colum reaches 16. Going as low as 0 will fill the screen with garbage!
    • increment the row because now everything gets displayed on the row 1.

    这篇关于操作或指令的参数大小非法 8086 子程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆