Home > Blockchain >  Accessing memory out of string bounds while printing
Accessing memory out of string bounds while printing

Time:10-16

Here's my ASM code:

bits 16
org 0x7c00

boot:
    mov bx, string
    call print_string

    hlt

string:
    db 'Booting OS', 0

printloop:
    ; Move the character into al so the BIOS interrupt prints it
    mov al, [bx]
    int 0x10
    ; Increment bx by 1 so it goes to the next character of the string
    add bx, 1
    
    ; Check if the value is 0, if so, exit out of the loop, if it's not 0, continue looping
    mov cx, [bx]
    cmp cx, 0x0000
    jne printloop
    jmp print_fin

print_string:
    pusha
    mov ah, 0x0e
    jmp printloop
    print_fin:
    popa
    ret


; Mark the device as bootable
times 510-($-$$) db 0 ; Add any additional zeroes to make 510 bytes in total
dw 0xAA55 ; Write the final 2 bytes as the magic number 0x55aa

Here's the output of the code:

Booting OS ŠÍƒÃ‹ƒù uòë`ëíaÃß

I'm fairly sure that's not what I entered.

I have no idea why it's going past the terminator..

Edit: I just tried setting the byte at the end of the string to 0x0000, incase that's somehow different from 0, it still went right past the terminator.

CodePudding user response:

This is one of those errors that would have gone by unnoticed if you had written the string right above the TIMES directive (and thus below the rest of the code). The first padding zero would have made it OK.

...
string:
    db 'Booting OS', 0

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

Edit: I just tried setting the byte at the end of the string to 0x0000, incase that's somehow different from 0, it still went right past the terminator.

Your edit could have solved the problem were there no misconception about what 0x0000 means. The way you write your numerical constant does not impose any size information on the DB directive.

db 'Booting OS', 0
db 'Booting OS', 0x00
db 'Booting OS', 0x0000
db 'Booting OS', 0x00000000

All the above encode the same, appending a single zero byte to the text.

Your effort to solve it using 0x0000 would have worked via the DW directive, appending a single zero word to the text:

db 'Booting OS'
dw 0x0000

But even here, you could have written the terminator in many ways:

dw 0
dw 0x00
dw 0x0000
dw 0x00000000

Unrelated to the bounds issue, but the print_string code is way too complicated. Better use code like this:

  mov  si, string
  call print_string  ; -> SI (AX)

...

; IN (si) OUT (si) MOD (ax)
print_string:
  push bx
  mov  bx, 0x00007   ; BH is DisplayPage, BL is GraphicsColor
  jmp  .begin
.loop:
  mov  ah, 0x0E      ; BIOS.Teletype
  int  0x10
.begin:
  mov  al, [si]      ; \ Alternatively, you can use LODSB here
  inc  si            ; /
  cmp  al, 0
  jne  .loop
  pop  bx
  ret

CodePudding user response:

I've fixed it, the problem was that I was using a 16 bit register to compare an 8 bit one (cx instead of cl), and the cmp was comparing the wrong values. (If I've gotten this wrong, please tell me what I got wrong. I've only just started learning ASM)

  • Related