问题
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
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
回答1:
PUSH count ; LINE ERROR PUSH colum ; LINE ERROR PUSH row ;LINE ERROR
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:
- 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
There's a superfluous
pop ax
right before the FIN label.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 branchjge HACER
(jump on greater or equal).
Putting it all together.
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
A final note.
To obtain a descent tree shape on the 80x25 textscreen, you should
- 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.
来源:https://stackoverflow.com/questions/41584877/argument-to-operation-or-instruction-has-illegal-size-8086-subroutine