5

LODSBを使用してコード内の文字列に相対アドレスをロードするために必要な最小限の手順は何ですか?

PXEを使用して起動する次のテストプログラムがあります。pxelinux.0経由と直接の2つの方法で起動します。直接起動すると、プログラムは両方の文字列を出力します。pxelinux.0を介して起動すると、最初の文字列のみが出力されます。

なんで?

回答: コードは問題ありません。初期アドレスの計算が間違っています。下記参照。

作業テクニック(両方):

  • 方向フラグをインクリメントするように設定し、cld
  • dsに設定cs
  • 文字列のアドレス(最初から)をsi
  • 開始オフセットをに追加しますsi

動作しないテクニック(pxelinuxの場合のみ):

  • に基づいて新しいセグメントアドレスを計算します(((cs << 4) + offset) >> 4)
  • それに設定dsします。(A000または07C0のいずれか)

マークダウンのバグを修正するためのここにテキスト

// 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

コンパイルは次のとおりです。

/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
4

2 に答える 2

4

最初の問題:

9020:FE00 ==> 9000:0000 ではなく A000:0000
その計算を行う grldrstart.S のコードを使用していました。grldrstart.S ルーチンにバグがあります。FE00 オフセットを取得し、4 ビット右にシフトしますが、符号を保持せずにシフトします。FE00 は負の数です。したがって、代わりに:

shrw   $4, %bx

だったはずです

sarw   $4, %bx   // Preserves sign!!

90200 + FE00 = 90200 - 200 = 90000

質疑応答:

LODSB を使用するには、次のことを行う必要があります。

  • 適切に設定dsする (そして正しい計算を使用する)
  • インクリメントとデクリメントにcldorを使用して、方向フラグを正しく設定しますstd
  • siソースバッファへのオフセットに設定します。
  • 有効なアドレスの読み取りは(ds << 4) + si
于 2010-03-21T15:22:12.270 に答える
0

ds を設定するには -->

csをプッシュ

ポップDS

于 2010-03-21T06:59:40.570 に答える