2013-09-11 3 views
2

어셈블리에서 선언 된 문자열을 반복하고 BIOS 인터럽트를 사용하여 인쇄 할 수있는 함수를 정의해야합니다. 16 비트 리얼 모드입니다. 이것은 교과서에서 약간의 부트 로더를 작성하는 연습이지만, 이는 초안 일 뿐이며 일부 물건이 누락 된 것으로 보입니다.미리 정의 된 함수를 사용하지 않고 어셈블리에서 문자열 인쇄

org 0x7c00 

mov bx, HELLO_MSG 
call print_string 

mov bx, GOODBYE_MSG 
call print_string 

jmp $    ;hang so we can see the message 

%include "print_string.asm" 

HELLO_MSG: 
    db 'Hello, World!', 0 

GOODBYE_MSG: 
    db 'Goodbye!', 0 

times 510 - ($ - $$) db 0 
dw 0xaa55 

내 print_string.asm은 다음과 같습니다 : 다음 코드를 주어졌다

print_string: 
    pusha 
    mov ah, 0x0e 

    loop: 
     mov al, bl 
     cmp al, 0 
     je return 
     int 0x10 
     inc bx 
     jmp loop 

    return: 
     popa 
     ret 

내가 뭘하는지 몇 가지 아이디어를 가지고 있지만,이 책은 어떻게 설명 할 수 없다 무언가를 반복 할 수 있습니다. C 언어로하는 방법을 알고 있지만, C 코드를 디버깅하는 것 이외의 다른 방법으로 어셈블리를 사용하는 것은 이번이 처음입니다. 에뮬레이터를 통해 부팅 할 때 두 줄의 횡설수설이 나오고 결국에는 실패로 끝나는 것을 볼 수 있습니다. 하하.

답변

2

글쎄, 그것은 함수를 호출하기 전에 문자열의 주소를 BX 레지스터에로드하는 것 같습니다.

실제 함수는 BX를 포인터로 사용하고 문자열의 끝에서 ASCII NUL에 도달 할 때까지 inc (inc bx)를 증가시키면서 문자열을 반복하려고하는 것처럼 보입니다 (cmp al, 0; je return) ...

...하지만 뭔가 잘못되었습니다. "mov al, bl"명령은 올바르지 않게 표시됩니다.이 명령은 주소의 하위 8 비트를 모두 ASCII NUL로 비교하기 때문에 비교가되지 않으므로 많은 의미가 없습니다. 나는 그것이 "mov al, [bx]"와 같은 어떤 것이어야한다고 생각합니다. 즉 BX 주소에 의해 참조 된 바이트를 AL 레지스터로 옮긴다. 비록 어셈블리로 작업 한 이후로 오랜 시간이 걸렸지 만 올바른 구문을 가지고 있지 않을 수도있다.

버그 때문에 10h 인터럽트는 문자열의 내용이 아닌 문자열의 주소를 기반으로 임의 문자를 인쇄합니다. 그것은 당신이보고있는 횡설수설을 설명 할 것입니다.

+0

감사합니다. 다른 어드레싱 모드가 어떻게 작동하는지 아직도 혼란 스럽다. 'op register'는 값을 직접 사용하는 것으로 보이며 'op [register]'는 "이 레지스터의 번호를 주소로 사용하십시오"라고 말합니다. – Hugo

+0

@Steven, 우연히도, 나는 OP에서 사용한 것과 같은 책을 사용하고 있습니다. 나는 또한 같은 일에 붙어 있고 이전에 구문을 시도했다. -'mov al, [bx]'. 그러나 NASM은 해당 라인에서 컴파일 오류 (잘못된 유효 주소)를 제공하고 있습니다. –

1

저는 여러분의 레지스터를 보존하는 int을 믿을 수 없다고 생각합니다. 따라서 여러분은 그것을 보호해야합니다. 또한 스티븐이 문자열 주소로드에 대해 지적한 내용은 다음과 같습니다.

; Print the string whose address is in `bx`, segment `ds` 
; String is zero terminated 
; 
print_string: 
    pusha 

loop: 
    mov al, [bx] ; load what `bx` points to 
    cmp al, 0 
    je return 
    push bx   ; save bx 
    mov ah, 0x0e ; load this every time through the loop 
         ; you don't know if `int` preserves it 
    int 0x10 
    pop bx   ; restore bx 
    inc bx 
    jmp loop 

return: 
    popa 
    ret 
+0

내가 사용하고있는 인터럽트는 분명히 Steven의 제안이 효과가 있었기 때문에 레지스터를 보존합니다. int 0x10은 ax 레지스터 만 봅니다. 하지만 고마워. – Hugo

+0

@Hugo, ok. 나는 아직도 당신이 신경 쓰는 레지스터를 저장하기 위해 레지스터 보존에 관한 문서화가 명백하지 않은 한 좋은 습관이라고 생각한다. 다른 int 호출을 처리 할 때 다른 사람의 ASM에 응답했고 등록 보존은 실제로이 경우 문제였습니다. 'print_string' 루틴에서'pusha'와'popa'를 부지런히 사용했다는 사실은 여러분을이 점에서도 저장했을 것입니다. – lurker

관련 문제