lundi 2 mars 2015

Using string in x86 assembly



I am trying to implement a function which tries to print string in 16-bit mode seen on QEmu:

kernel.c file:



void main()
{
char* str = "Hello World!";
printString(str);
}


The printString function is defined in another file printString.c:



int printString(char* string)
{
int i = 0;
while (*(string + i) != '\0')
{
char al = *(string + i);
char ah = 0xe;
int ax = ah * 256 + al;
interrupt(0x10,ax,0,0,0);
i++;
}
return i;
}


The interrupt function calls BIOS interrupt, as given in the first argument of the function with other arguments specifying respectively the contents of ax, bx, cx and dx registers. Here is the code



.global _interrupt
_interrupt:
push bp
mov bp, sp
push si
push ds
mov ax, #0x100
mov ds, ax
mov ax, [bp + 0x4]
mov si, #intr
mov [si + 1], al
pop ds
mov ax, [bp + 0x6]
mov bx, [bp + 0x8]
mov cx, [bp + 0xa]
mov dx, [bp + 0xc]
intr: int #0x0
pop si
pop bp
ret


I compile the .c files using the command:



bcc -ansi -c -o <name.o> <name.c>


And link them using:



ld86 -o kernel -d kernel.o interrupt.o printString.o


Instead of printing "Hello World!", the program prints "S" on the screen. I loaded the kernel.c file at the address 0x1000. I saw the dis-assembly of the code:



0x1000: push %bp
0x1001: mov %sp,%bp
0x1003: push %di
0x1004: push %si
0x1005: dec %sp
0x1006: dec %sp
0x1007: mov $0xc8,%bx
0x100a: mov %bx,-0x6(%bp)
0x100d: pushw -0x6(%bp)
0x1010: call 0x1058


For the pointer to be passed to the printString function (in kernel.c file) the argument passed is 0xc8 which contains 0xf000ff53. Thus 53, which is the ASCII code for S gets printed on the screen.

How should I pass the string to the printString function and why doesn't the above code works?

Please tell me if I need to give more explanation.




Aucun commentaire:

Enregistrer un commentaire