操作或指令的参数大小非法 8086 子程序 [英] argument to operation or instruction has illegal size 8086 subroutine
问题描述
我开始用微处理器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 themov 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屋!