Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NASM x86 using of nonexisting segment register 7

Tags:

x86

assembly

nasm

I'm currently writing a simple program in x86 assembly that gets the data at an arbitrary memory address and prints it to the terminal in hexadecimal. It's being assembled in NASM 2.12.02 and I'm running the resulting bin with bochs 2.6.8. I've written a routine called print_hex.asm that uses db to define an index of ascii characters, as seen below.

ascii_table: db "0123456789ABCDEF"

When assembling the full program and running the result, the same line

(an increasing number)i[CPU0 ] MOV_EwSw: using of nonexisting segment register 7

prints out over an over again to terminal preceded by a number that keeps increasing. What's strange is if I change the line to

ascii_table: db "0123456789ABC"

by simply omitting the last three letters of the string, it works just fine (although the assembled program gets a runtime error when it tries to convert hex values of D, E or F)

What's going on here? Am I not allowed to declare so much data in a row? Is NASM bugging out on me?

Edit: See below for full source code. Note that it is still a work in progress and might have logic errors elsewhere.

print_hex:                        ; prints the value stored at bx in hex
    pusha                         ; push all the local registers to the stack
    ascii_table:                  ; define a table to store ascii characters for conversion
        db "0123456789ABCDEF"
    mov ah, 0x0e                  ; move 0x0e to the high byte of ax in preparation for a teletype interrupt
    mov al, "0"                   ; move the ascii char 0 to the lower byte of ax
    int 0x10                      ; perform a teletype interrupt
    mov al, "x"                   ; move the ascii char x to the lower byte of ax
    int 0x10                      ; perfrom a teletype interrupt
    mov dx, 0                     ; move 0 to dx in preparation for the loop
    mov cx, 0                     ; zero out cx
    hex_print_loop_start:
        mov cl, bl                ; move bl to cl to isolate the lowest nybble of bx
        add cl, ascii_table       ; set the table offset with cx
        mov al, cl                ; get the value at the offset index of the table and store it in al for printing
        int 0x10                  ; perform a teletype interrupt
        inc dx                    ; increment dx by one
        shr bx, 1                 ; shift bx right in preparation for reading the next character
        cmp dx, byte 0x04         ; check if the loop has been performed 4 times
        jl hex_print_loop_start   ; if it hasn't been performed 4 times, jump to the beginning of the loop
    popa                          ; restore local registers
    ret                           ; return
like image 371
qaxf6auux Avatar asked Mar 12 '23 14:03

qaxf6auux


1 Answers

You must move the string data outside the code, because the CPU, after executing pusha instruction will execute the string as instructions. Your string is interpreted as the following code:

'01'  30 31  XOR BYTE PTR [BX+DI],DH
'23'  32 33  XOR DH,BYTE PTR [BP+DI]
'45'  34 35  XOR AL,35H
'67'  36:37  SS:AAA                   ;  Superfluous prefix
'89'  38 39  CMP BYTE PTR [BX+DI],BH
'A'   41     INC CX
'B'   42     INC DX
'C'   43     INC BX
'D'   44     INC SP
'E'   45     INC BP
'F'   46     INC SI

As long as these instructions are pretty random, so random behavior is expected. Notice also, that the stack pointer is modified, so on the exit of the procedure more chaos is expected.

like image 199
johnfound Avatar answered Mar 19 '23 22:03

johnfound