Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 引导加载程序不会减少循环中的寄存器值_Assembly_X86_X86 16_Bootloader - Fatal编程技术网

Assembly 引导加载程序不会减少循环中的寄存器值

Assembly 引导加载程序不会减少循环中的寄存器值,assembly,x86,x86-16,bootloader,Assembly,X86,X86 16,Bootloader,我正在用汇编语言创建一个引导加载程序;让它使用循环创建圣诞树,并使用LinuxBash运行它,但我在尝试从寄存器中减去以终止循环时遇到了一个问题。 我试图创建一个函数以减少寄存器的值,但函数主干只运行一次 [BITS 16] [ORG 0x7C00] top: ;; Put 0 into ds (data segment) ;; Can't do it directly mov ax,0x0000 mov ds,ax ;; si is the

我正在用汇编语言创建一个引导加载程序;让它使用循环创建圣诞树,并使用LinuxBash运行它,但我在尝试从寄存器中减去以终止循环时遇到了一个问题。 我试图创建一个函数以减少寄存器的值,但函数主干只运行一次

[BITS 16] 
[ORG 0x7C00] 
top: 
    ;; Put 0 into ds (data segment) 
    ;; Can't do it directly 
    mov ax,0x0000 
    mov ds,ax 
    ;; si is the location relative to the data segment of the 
    ;; string/char to display  
    mov ch, 5 ;
    mov cl, 1 ;
    call Pyramid
    mov ch, 4 ;
    mov cl, 3
    mov al, 2
    call Trunk
    jmp $ ; Spin 
    
Pyramid:
    mov dh, ch ; print the dot 
    mov dl, cl; dec ch
    call SPACE;
    call DO;
    dec ch;
    add cl, 2;
    mov si, cr 
    call writeString ; See below 
    cmp ch, 0 ; compare to see if what is store in ch is 0
    jne Pyramid ; if ch does not contain 0 call dotsLoop again.
    ret ;
    
Trunk: 
    mov dh, ch;
    mov dl, cl;
    call SPACE
    call DO
    call TLevel
    mov si, cr
    call writeString
    cmp al, 0
    jmp Trunk
    ret ;
    
TLevel:
    dec al
    ret 
SPACE:
    mov si, S;
    call writeString;
    dec dh;
    cmp dh, 0;
    jne SPACE;
    ret;
DO:
    mov si, D;
    call writeString;
    dec dl;
    cmp dl, 0;
    jne DO;
    ret;
writeString: 
    mov ah,0x0E ; Display a chacter (as before) 
    mov bh,0x00 ;
    mov bl,0x07; 
nextchar: 
    Lodsb ; Loads [SI] into AL and increases SI by one 
    ;; Effectively "pumps" the string through AL 
    cmp al,0 ; End of the string? 
    jz done 
    int 0x10 ; BIOS interrupt 
    jmp nextchar 
done: 
    ret 
    S db ' ',0 ; Null-terminated 
    D db '*',0 ;
    cr db 13,10,0;
    times 510-($-$$) db 0;
    dw 0xAA55
我试图创建一个函数以减少寄存器的值,但函数主干只运行一次

[BITS 16] 
[ORG 0x7C00] 
top: 
    ;; Put 0 into ds (data segment) 
    ;; Can't do it directly 
    mov ax,0x0000 
    mov ds,ax 
    ;; si is the location relative to the data segment of the 
    ;; string/char to display  
    mov ch, 5 ;
    mov cl, 1 ;
    call Pyramid
    mov ch, 4 ;
    mov cl, 3
    mov al, 2
    call Trunk
    jmp $ ; Spin 
    
Pyramid:
    mov dh, ch ; print the dot 
    mov dl, cl; dec ch
    call SPACE;
    call DO;
    dec ch;
    add cl, 2;
    mov si, cr 
    call writeString ; See below 
    cmp ch, 0 ; compare to see if what is store in ch is 0
    jne Pyramid ; if ch does not contain 0 call dotsLoop again.
    ret ;
    
Trunk: 
    mov dh, ch;
    mov dl, cl;
    call SPACE
    call DO
    call TLevel
    mov si, cr
    call writeString
    cmp al, 0
    jmp Trunk
    ret ;
    
TLevel:
    dec al
    ret 
SPACE:
    mov si, S;
    call writeString;
    dec dh;
    cmp dh, 0;
    jne SPACE;
    ret;
DO:
    mov si, D;
    call writeString;
    dec dl;
    cmp dl, 0;
    jne DO;
    ret;
writeString: 
    mov ah,0x0E ; Display a chacter (as before) 
    mov bh,0x00 ;
    mov bl,0x07; 
nextchar: 
    Lodsb ; Loads [SI] into AL and increases SI by one 
    ;; Effectively "pumps" the string through AL 
    cmp al,0 ; End of the string? 
    jz done 
    int 0x10 ; BIOS interrupt 
    jmp nextchar 
done: 
    ret 
    S db ' ',0 ; Null-terminated 
    D db '*',0 ;
    cr db 13,10,0;
    times 510-($-$$) db 0;
    dw 0xAA55
在TLevel例程中,您使用
AL
寄存器来计算Trunk的迭代次数,但您忘记了所有对SPACE、DO和writeString的调用都会对
AL
中的值进行重击

选择不同的寄存器作为计数器,或在writeString过程中保留
AX
寄存器

writeString:
    PUSH AX       ; PRESERVE AX
    mov  ah, 0x0E 
    mov  bx, 0x0007 
nextchar: 
    Lodsb 
    cmp  al, 0
    je   done 
    int  0x10
    jmp  nextchar 
done:
    POP  AX       ; RESTORE AX
    ret

为了根据
AL
中的计数器实际循环,您需要将无条件跳转
jmp
替换为条件跳转
jne

请注意,只需执行
dec al
的单独例程是浪费。
你为什么不这样写:

Trunk: 
    mov  dx, cx   ; LOAD BOTH COUNTERS IN ONE INSTRUCTION
    call SPACE
    call DO
    mov  si, cr
    call writeString
    dec  al
    jnz  Trunk
    ret

这是一个引导加载程序。您不能将其作为本机Linux可执行文件运行。如果将其构建到ELF可执行文件中,当它到达
int0x10
时,它将崩溃。我想这不是你真正在做的,你只是把它描述错了。希望您正在使用一个调试器运行它,该调试器允许您单步执行。