Was ist erforderlich, um LODSB in der Montage?
Was ist die minimale Menge von Schritten erforderlich, um LODSB laden eine relative Adresse auf einen string in meinem code?
Ich habe Folgendes test-Programm, dass ich per PXE zu Booten. Ich boot es zwei Möglichkeiten: via pxelinux.0 und direkt. Wenn ich das Booten direkt, mein Programm druckt sowohl strings. Wenn ich boot via pxelinux.0, es druckt nur die erste Zeichenfolge.
Warum?
Antwort: Der code ist in Ordnung, die erste Adresse ist die Mathematik falsch. Siehe unten.
Arbeitstechnik (für beide):
- Die Richtung fahne zu erhöhen,
cld
- Set
ds
zucs
- Setzen Sie die Adresse (vom Anfang) von string in
si
- Fügen Sie den Start-offset zu
si
Nicht-Arbeit-Technik (nur für pxelinux):
- Berechnen Sie ein neues segment-Adresse, basierend auf
(((cs << 4) + offset) >> 4)
- Set
ds
zu. (entweder A000 oder 07C0)
text hier zu fix bug in markdown
//Note: If you try this code, don't forget to set
// the "#if 0" below appropriately!
.text
.globl start, _start
start:
_start:
_start1:
.code16
jmp real_start
. = _start1 + 0x1fe
.byte 0x55, 0xAA
//Next sector
. = _start1 + 0x200
jmp real_start
test1_str:
.asciz "\r\nTest: 9020:fe00"
test2_str:
.asciz "\r\nTest: a000:0000"
real_start:
cld //Make sure %si gets incremented.
#if 0
//When loaded by pxelinux, we're here:
//9020:fe00 ==> a000:0000
//This works.
movw $0x9020, %bx
movw %bx, %ds
movw $(test1_str - _start1), %si
addw $0xfe00, %si
call print_message
//This does not.
movw $0xA000, %bx
movw %bx, %ds
movw $(test2_str - _start1), %si
call print_message
#else
//If we are loaded directly without pxelinux, we're here:
//0000:7c00 ==> 07c0:0000
//This works.
movw $0x0000, %bx
movw %bx, %ds
movw $(test1_str - _start1), %si
addw $0x7c00, %si
call print_message
//This does, too.
movw $0x07c0, %bx
movw %bx, %ds
movw $(test2_str - _start1), %si
call print_message
#endif
//Hang the computer
sti
1:
jmp 1b
//Prints string DS:SI (modifies AX BX SI)
print_message:
pushw %ax
jmp 2f
3:
movb $0x0e, %ah /* print char in AL */
int $0x10 /* via TTY mode */
2:
lodsb (%si), %al /* get token */
cmpb $0, %al /* end of string? */
jne 3b
popw %ax
ret
.balign 0x200
Hier ist die Zusammenstellung:
/usr/bin/ccache gcc -Os -fno-stack-protector -fno-builtin -nostdinc -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 -DSUPPORT_GRAPHICS=1 -DHAVE_CONFIG_H -I. -Wall -ggdb3 -Wmissing-prototypes -Wunused -Wshadow -Wpointer-arith -falign-jumps=1 -falign-loops=1 -falign-functions=1 -Wundef -g -c -o ds_teststart_exec-ds_teststart.o ds_test.S
/usr/bin/ccache gcc -g -o ds_teststart.exec -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000 ds_teststart_exec-ds_teststart.o
objcopy -O binary ds_teststart.exec ds_teststart
- Wenn das problem sich herausstellt, etwas ganz anderes geht, werd ich wieder Wort die ganze Frage für die Antwort.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erste problem:
9020:FE00 ==> 9000:0000 und nicht A000:0000
Ich war mit einigen code aus grldrstart.S, das bedeutet, dass die Berechnung. Da ist ein Fehler in der grldrstart.S routine. Es nimmt die FE00-offset und schiebt Sie nach rechts 4 bits, aber es tut es ohne die Bewahrung der Zeichen; FE00 ist eine negative Zahl. Also statt:
sollte es gewesen
90200 + FE00 = 90200 - 200 = 90000
Frage Beantworten:
Um LODSB, müssen Sie:
ds
richtig (und richtig Mathematik)cld
oderstd
für Inkrement-und Dekrement -si
auf den offset an den Quell-Puffer.(ds << 4) + si
Festgelegt ds -->
push cs
pop ds
(0000 << 4) + 7c00 + 40
oder(07c0 << 4) + 40