操作或指令的参数具有非法大小 8086 子例程

argument to operation or instruction has illegal size 8086 subroutine

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

argument to operation or instruction has Illegal size

在第 21 行,即执行 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

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

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

您的程序还有一些问题:

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

    • 让过程通过写作为它的最后一条指令来完成:

      ret 6
      
    • 在调用 return 之后添加堆栈指针:

      call DIBUJA
      add  sp, 6
      
  • FIN 标签之前有一个多余的 pop ax

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


把它们放在一起。

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 文本屏幕上获得下降树形状,您应该

  • colum 达到 16 时停止主循环。低至 0 将用垃圾填满屏幕!
  • 增加 因为现在所有内容都显示在第 1 行。