Странный вывод строки из INT 0x10 - PullRequest
0 голосов
/ 09 марта 2012

Привет, я перенаправил прерывание переполнения при разделении, чтобы указать на свое специально созданное прерывание, которое выводит на экран «привет, я здесь», вместо этого выводятся странные символы ascii. Может кто-нибудь сказать мне, почему? вот код

[ORG 100h]
jmp start
message:    dw      'hello man here i am'


prntstr:    push ax
            push bx
            push cx
            push dx
            push si
            push di
            push bp
            push ds
            push es
            push cs
            pop ds

            mov ah, 0x13
            mov al, 1
            mov bh, 0
            mov bl, 7
            mov dx,0x0a03
            mov cx,11
            push cs
            push es
            mov bp,message
            int 0x10
            pop es
            pop ds
            pop bp
            pop di
            pop si
            pop dx
            pop cx
            pop bx
            pop ax
            ret
tsr:        mov ah, 0
            int 0x16
            call prntstr
            iret
            ;mov ah,4ch
            ;mov al, 6
            ;int 0x21
            ;iret


divs:       mov ax,0x8569
            mov dl,2
            div dl
            ret


start:      xor ax,ax
            mov es,ax
            mov word[es:0*4], tsr
            mov [es:0*4+2],cs
            call divs

            mov ax,0x4c00
            int 0x21

еще одна вещь, которую я не понимаю в коде, это где я установил смещение на es: 0 * 4 - я предполагаю, что 00 - это место прерывания переполнения разделения? что 0 * 4 для coz что-либо умноженное на ноль будет означать то же самое, так почему 4? заранее спасибо

Ответы [ 2 ]

1 голос
/ 09 марта 2012

Что касается странных проблем с персонажем, я думаю:

push cs
push es

должно быть:

push cs
pop  es

В противном случае:

  1. Ваши толчки и треск не сбалансированы.
  2. Ваш регистр сегмента es не настроен для es:bp, чтобы правильно указывать на сообщение. Он будет печатать все, что находится со смещением message в сегменте, на который es указывал, когда сработало ваше прерывание, а не в сегменте кода, где находится ваше фактическое сообщение.
  3. Это также в конечном итоге приведет к краху.

По вопросу 0*4 я не уверен. Прошло много времени с тех пор, как я сделал x86, но я знаю, что вы можете масштабировать режимы косвенной адресации, такие как:

mov eax, dwarray[edx*4]

для обеспечения правильного доступа к ячейкам памяти. Это увеличило edx до правильного значения перед добавлением к базовому адресу dwarray.

Я не думаю, что это было необходимо для немедленного смещения, поэтому я подозреваю, что это был просто стандартный код для возможности любого прерывания , просто заменив 0 соответствующим номером прерывания.

И, кроме того, вы, вероятно, не не хотите изменять векторы прерываний, не гарантируя, что прерывания будут отключены во время процесса. Если прерывание сработает после , когда вы записали смещение tsr, но до , когда вы написали сегмент, результаты не будут хорошими.

0 голосов
/ 09 марта 2012

У вас есть несколько проблем в вашем коде. Смотрите комментарии:

[ORG 100h]
jmp start
message:    db      'hello man here i am' ; chars are 8-bit, hence db, not dw
msglen      equ $ - message ; calculate message length

prntstr:    push ax
            push bx
            push cx
            push dx
            push si
            push di
            push bp
            push ds
            push es

            ;push cs ; not really needed here
            ;pop ds

            mov ah, 0x13
            mov al, 1
            mov bh, 0
            mov bl, 7
            mov dx,0x0a03
            mov cx,msglen ; use proper message length

            push cs
            pop es ; not "push es" - copy'n'paste bug !!!

            mov bp,message
            int 0x10

            pop es
            pop ds
            pop bp
            pop di
            pop si
            pop dx
            pop cx
            pop bx
            pop ax
            ret

tsr:
            call prntstr

            ; skip DIV (by advancing IP) to avoid infinite loop on DIV
            push bp
            mov bp, sp
            add word [bp+1*2], divend-divstart; IP (location of divstart) on the stack
            pop bp

            push ax ; save AX because int 0x16 will change it
            mov ah, 0
            int 0x16
            pop ax ; restore AX

            iret

divs:       mov ax,0x8569
            mov dl,2
divstart:
            div dl
divend:
            ret

start:
            mov  ax, 3
            int 0x10 ; clear screen by setting mode 3

            xor ax,ax
            mov es,ax

            cli                 ; update ISR address w/ ints disabled
            push word[es:0*4+2] ; preserve ISR address
            push word[es:0*4]
            mov word[es:0*4], tsr
            mov [es:0*4+2],cs
            sti

            call divs

            cli                 ; update ISR address w/ ints disabled
            pop  word[es:0*4]   ; restore ISR address
            pop  word[es:0*4+2]
            sti

            mov ax,0x4c00
            int 0x21

4 - размер дальнего указателя (2 байта для смещения и 2 байта для селектора сегмента). Таким образом, для int 0 адрес в таблице векторов прерываний будет 0*4, для int 1 это будет 1*4, для int n это будет n*4. В этом конкретном случае умножение не является необходимым, но оно все равно не повлияет на генерацию кода, поскольку ассемблер вычислит и заменит 0 для 0*4 и 2 для 0*4+2.

...