我正在学习汇编并成功解决了打印here
中的问题现在我有另一个问题。
我正在使用emu8086。我有这个代码使用带有背景颜色的空格字符打印一个minion的图像。我设法让它每行打印图像,但当它到达第26行时,它停止打印,并出现“错误中断”错误。
任何人都可以帮助我。
以下是整个代码:
org 100h
name "charchar"
org 100h
;buhok line 1 (Grey)
mov ax,0B800h
mov es,ax
mov di,56;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
;buhok line 2
mov ax,0B800h
mov es,ax
mov di,200;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,202;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,208;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,210;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,214;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,216;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,218;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,222;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,226;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,230;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,047 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,234;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,047 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
;buhok line 3
mov ax,0B800h
mov es,ax
mov di,352;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,354;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,356;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,358;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,360;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,362;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,364;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,366;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,092 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,368;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,370;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,372;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,374;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,376;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,378;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,382;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,384;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,386;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,179 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,388;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,47 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,390;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,47 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,392;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,47 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,394;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,47 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,396;<target_address = y*160 + x*2> ; es:di set up
mov ah,00001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,47 ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
........
;line 26 Hand, Body blue
mov ax,0B800h
mov es,ax
mov di,4172;<target_address = y*160 + x*2> ; es:di set up
mov ah,10001000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,' ' ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov al,' ' ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov al,' ' ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov al,' ' ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov ax,0B800h
mov es,ax
mov di,4188;<target_address = y*160 + x*2> ; es:di set up
mov ah,11101000b;<color_attribute_for_whole_string>
; now the print by letter gets here
mov al,' ' ; al = letter, ah = attribute (ax set up)
stosw ; [es:di] = ax, di += 2
mov dl,0 ;X (SCREEN COORDINATE).
mov dh,5 ;Y (SCREEN COORDINATE).
int 10h ;BIOS SCREEN SERVICES.
;FINISH THE PROGRAM PROPERLY.
mov ax,4c00h
int 21h
ret
答案 0 :(得分:3)
鉴于使用0B800h作为视频片段和使用EMU8086,很明显您正在使用80x25文本屏幕。此屏幕后面的视频RAM占用总共4000个字节。当您的程序在此区域下方的位置(使用mov di,4172
和mov di,4188
)时,它会有效地在屏幕外写入。
如果您在真正的BIOS / DOS环境中运行此代码,那么这些屏幕外写入只会进入额外的显示页面,但由于这是EMU8086,因此这些额外的显示页面不存在。所以你永远不应该在这4000字节之外写。
由于@Ruud说您忘了在AH寄存器中为 SetCursor 功能指定功能代码。
mov dl, 0 ;X (SCREEN COORDINATE).
mov dh, 5 ;Y (SCREEN COORDINATE).
mov ah, 2
int 10h ;BIOS SetCursor.
;line 26 Hand, Body blue
由于您将屏幕的第一行命名为第1行,因此您在此评论下面(尝试)写入的行是第27行 !
3840 -> 3999 line 25
4000 -> 4159 line 26
4160 -> 4319 line 27 <-- 4172 and 4188 belong here!
mov ax,0B800h mov es,ax
为什么这么多次重复这些说明?将ES段寄存器设置为正确值后,它将保持设置为多个输出。
答案 1 :(得分:1)
The major problem is missing ah
value for the last int 10h
. At that point the ah
is 0xE8
(attribute from hand/body blue), and int 10h
doesn't have such function.
Also clean up your notation a bit, when describing problems, etc. Think for a while about the numbers you are using, let me try to summarize:
Used text mode has resolution 80x25 characters (you can also try to select other modes, VGA has several of them).
Address of character is (y * 80 + x) * 2
, where y
is [0,24] and x is [0,79]. Note how the maximum valid value for x/y is "size-1", not size itself. So already y = 25
would put you off the visible area of screen.
From this I would expect you to use "line 0" to "line 24", not "line 1"->"line 25", as it is using directly the y
value for line description.
But writing into off-screen area is normally a valid operation on VGA IBM PC, and actually you may tamper (at least on real HW, not sure about emu8086) with registers of VGA card to move the start of video memory from B800:0000 further away, creating "fast scrolling" without rewriting the video memory content for each char. It just doesn't make sense in your example as you don't scroll the screen (and from the problems you have I would say a direct modification of VGA control registers is a bit advanced topic for you at the moment).
There are many redundancies in your code, the setup of es
is just one of them (as Fifoernik noted).
Also things like mov di,396;<target_address = y*160 + x*2> ; es:di set up
IMO are complicating it for you without any benefit.
I can't try emu8086 myself, but I would be very surprised if mov di,2*160 + 38*2
would not compile, which will allow you to keep "[x,y]" visible for human reading the source (of course in disassembly there will be only resulting 396 value, which is compiled into outputted machine code).
(I would be surprised up to a point to suggest you to ditch emu8086 and use NASM + dosbox + some DOS debugger, that one also emulates VGA in very decent manner, including many control registers, so if you ever want to relive old era of setting graphic card directly, most of the VGA stuff should work with dosbox, if not all)
And for example after mov di,390 ... stosw
in next code you do mov di,392
, while the di
already is 392 (you even have that in comment after stosw
instruction). You can "chain" those stosw
operations interleaved only with changing ah
and/or al
as needed, for writing consecutive characters on single line.
Maybe you should stop for a while with creating the ASCII art, and step over your code in debugger few times, plus watch how registers change, and try to better understand how CPU works, it will save you some time later, as you will be able to write shorter code (but try to keep it readable).