【问题标题】:What is required to use LODSB in assembly?在汇编中使用 LODSB 需要什么?
【发布时间】:2011-01-29 21:21:48
【问题描述】:

使用 LODSB 将相对地址加载到我的代码中的字符串所需的最少步骤是什么?

我有以下使用 PXE 引导的测试程序。我通过两种方式启动它:通过 pxelinux.0 和直接。如果我直接启动它,我的程序会打印两个字符串。如果我通过 pxelinux.0 启动,它只会打印第一个字符串。

为什么?

答案: 代码没问题,初始地址数学错误。见下文。

工作技术(两者都适用):

  • 将方向标志设置为递增,cld
  • ds设置为cs
  • 将字符串的地址(从开始)放入si
  • 将起始偏移量添加到si

非工作技术(仅适用于 pxelinux):

  • 根据(((cs << 4) + offset) >> 4)计算新的段地址
  • ds 设置为该值。 (A000 或 07C0)

text here to 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

这是汇编:

/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

【问题讨论】:

  • 如果问题完全是其他问题,我会重新措辞整个问题的答案。

标签: assembly x86 segments


【解决方案1】:

第一个问题:

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(并使用正确的数学)
  • 正确设置方向标志,使用cldstd 进行递增和递减
  • si 设置为源缓冲区的偏移量。
  • 读取的有效地址为(ds << 4) + si

【讨论】:

    【解决方案2】:

    设置 ds -->

    推送cs

    流行音乐

    【讨论】:

    • @smiffy: 但我想计算一个新的段地址,这样我就不必将原始偏移量添加到每条基于 ds:si 的指令中。所以我的程序中偏移量 0x40 处的字符串可以是 (0000 << 4) + 7c00 + 40(07c0 << 4) + 40
    猜你喜欢
    • 2019-02-19
    • 2011-02-02
    • 1970-01-01
    • 2012-08-19
    • 2010-10-21
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2017-05-25
    相关资源
    最近更新 更多