Сборка x86, порядок байтов не соблюдается (или нет?) (Linux)

Я новичок в программировании на ассемблере и написал небольшую программу для печати целого числа с помощью системного вызова sys_write. Вот мой код:

section .data

N: dw 216
chr: dw ,0,0,0,0x0a

section .bss

section .text

  global _start

_start:
            xor ax, ax
            mov ax, word [N]
            mov cx, 10 
            mov ebx,4

shift_while: div cx 
             add dx, 0x0030
             mov word [chr+ebx],dx
             sub ebx, 2 
             xor dx, dx
             cmp ax, 0
             jne shift_while
             call printchar

exit:        mov eax, 1
             mov ebx, 0
             int 80h


printchar:  pushad
            mov eax, 4
            mov ebx, 1
            mov ecx, chr
            mov edx, 8
            int 80h
            popad
            ret

У меня жестко закодировано 216, номер для печати, и я получаю правильный вывод. Однако меня смущает инструкция «mov word [chr+ebx],dx». dx содержит 0x0032 в первой итерации, поэтому по адресу [chr+ebx] это значение должно храниться как 32 00 (hex). Но когда я проверил память chr с помощью gdb, он показал:

(gdb) x /5hx 0x80490d2
0x80490d2 <chr>:    0x0032  0x0031  0x0036  0x000a

то, что я ожидал, было 0x3200 0x3100 0x3600 x0a00, и думал, что мне придется выполнить дальнейшие манипуляции с памятью, чтобы получить правильный результат. Я ошибаюсь где-то с этим. Есть вещи, которых я не вижу. Я был бы очень признателен за небольшую помощь здесь. Это мой первый первый пост на stackoverflow.


person san216    schedule 08.02.2011    source источник


Ответы (2)


Это просто представление - то, что у вас есть в памяти с побайтовой точки зрения,

32 00 31 00 26 00 0a 00

но когда вы рассматриваете это как 16-битные значения, это

0032 0031 0026 000a

Точно так же, если бы вы рассматривали его как 32-битные значения, это было бы:

00310032 000a0026

Такова странность прямого порядка следования байтов. ;-)

person Paul R    schedule 08.02.2011
comment
Да, прямой порядок байтов кажется странным с точки зрения просмотра памяти. Это имеет несколько больше смысла в вычислительном отношении. Я программирую 8086 с 1983 года: до сих пор требуется некоторая преднамеренная начальная концентрация, чтобы понять, что отображается. - person wallyk; 08.02.2011
comment
@BlackBear: да, когда мы записываем числа, мы записываем их в формате с прямым порядком байтов, поэтому прямой порядок байтов кажется более естественным и интуитивно понятным. Для прямого порядка байтов вы должны продолжать концептуально менять порядок байтов, чтобы сопоставлять многобайтовые значения и байты в порядке памяти. - person Paul R; 08.02.2011
comment
@wallyk, @BlackBear и др.: или вы можете смотреть на память справа налево (с наименьшим адресом памяти справа). С этим представлением все снова сопоставляется. - person Bahbar; 09.02.2011
comment
Я ссылаюсь, чтобы думать об ОЗУ сверху вниз. Облегчает сопоставление с прямым и обратным порядком байтов. - person Brian Knoblauch; 16.02.2011
comment
@Brian: но тогда строки и т. Д. Задом наперед? - person Paul R; 16.02.2011

gdb помогает вам здесь.

Вы запросили формат h (halfword) на платформе с прямым порядком байтов, поэтому для вас он декодирует память как 16-битные значения с прямым порядком байтов.

Если вместо этого вы используете формат b, вы увидите что-то более похожее на то, что вы ожидали.

person Matthew Slattery    schedule 08.02.2011
comment
Да, я заменил «h» на «b» и получил правильный результат, но это вызвало еще одно сомнение в том, как работает системный вызов sys_write (mov eax, 4... int 80h). Я не знаю точной реализации sys_write, так что это может показаться немного глупым. ch в памяти: (gdb) x /8bx 0x80490d2 0x80490d2 <chr>: 0x32 **0x00** 0x31 **0x00** 0x36 **0x00** 0x0a **0x00**. Я по-прежнему выводил на консоль как 216**. Что делает sys_write с ошибкой 0x00. Если бы это было chr: db Hello World, sys_write напечатала бы строку, читая каждый байт отдельно. Решают ли ключевые слова, такие как db или dw? - person san216; 09.02.2011
comment
Нет, db и dw определяют только то, как сам ассемблер обрабатывает значения. sys_write записывает это как 8 байт -- здесь, в файловый дескриптор 1 (стандартный вывод), который подключен к вашей консоли. Байты 0x00 интерпретируются драйвером устройства терминала консоли как управляющие символы бездействия (ASCII NUL). - person Matthew Slattery; 09.02.2011