Порядковый номер внутри регистров процессора - PullRequest
6 голосов
/ 22 декабря 2010

Мне нужна помощь в понимании порядка байтов внутри регистров ЦП процессоров x86.Я написал эту небольшую программу сборки:

section .data
section .bss

section .text
    global _start
_start:
    nop
    mov eax, 0x78FF5ABC
    mov ebx,'WXYZ'
    nop  ; GDB breakpoint here.
    mov eax, 1
    mov ebx, 0
    int 0x80

Я запустил эту программу в GDB с точкой останова на строке номер 10 (прокомментировано в приведенном выше источнике).В этой точке останова info registers показывает значения eax=0x78ff5abc и ebx=0x5a595857.

Поскольку коды ASCII для W, X, Y, Z равны 57, 58, 59, 5A соответственно;и Intel имеет младший порядок байтов, 0x5a595857 выглядит как правильный порядок байтов (сначала младший байт).Почему тогда вывод для eax-регистра 0xbc5aff78 (сначала младший байт числа 0x78ff5abc) вместо 0x78ff5abc?

Ответы [ 4 ]

17 голосов
/ 22 декабря 2010

Порядковый номер в регистре не имеет смысла, так как порядковый номер описывает, если порядок байтов от низкого до высокого адреса памяти или от высокого до низкого адреса памяти.Регистры не адресуются в байтах, поэтому в регистре нет низкого или высокого адреса.То, что вы видите, это то, как ваш отладчик распечатывает данные.

12 голосов
/ 22 декабря 2010

Ассемблер по-разному обрабатывает две константы.Внутри значение в регистре EAX хранится в формате с прямым порядком байтов.Вы можете увидеть это, написав:

mov eax, 1

Если вы осмотрите регистр, вы увидите, что его значение равно 0x00000001.

Когда вы скажете ассемблеру, что вы хотите константузначение 0x78ff5abc, это именно то, что хранится в регистре.Старшие 8 битов EAX будут содержать 0x78, а регистр AL содержит 0xbc.

Теперь, если вы хотите сохранить значение из EAX в памяти, оно будет заложенов памяти в обратном порядке.То есть, если бы вы написали:

mov [addr],eax

А затем проверили память в [addr], вы увидите 0xbc, 0x5a, 0xff, 0x78.

В случае 'WXYZ', ассемблер предполагает, что вы хотите загрузить значение таким образом, что если бы вы записали его в память, оно было бы расположено как 0x57, 0x58, 0x59, 0x5a.

Посмотрите на байты кодачто генерирует ассемблер, и вы увидите разницу.В случае mov eax,0x78ff5abc вы увидите:

<opcodes for mov eax>, 0xbc, 0x5a, 0xff, 0x78

В случае mov eax,WXYZ вы увидите:

<opcodes for mov eax>, 0x57, 0x58, 0x59, 0x5a
6 голосов
/ 22 декабря 2010

Endianness имеет смысл только для памяти, где каждый байт имеет числовой адрес. Когда MSByte значения помещается в более высокий адрес памяти, чем LSByte, он называется Littte Endian, и это порядковый номер любого процессора x86.

В то время как для целых чисел различие между LSByte и MSByte очевидно:

    0x12345678
MSB---^^    ^^---LSB

Это не определено для строковых литералов! Не очевидно, какую часть WXYZ следует считать LSB или MSB:

1) Самый очевидный способ,

'WXYZ' ->  0x5758595A

приведет к порядку памяти ZYXW.

2) Не совсем очевидный способ, когда порядок памяти должен соответствовать порядку литералов:

'WXYZ' ->  0x5A595857

Ассемблер должен выбрать один из них, и, очевидно, он выбирает второй.

4 голосов
/ 26 декабря 2018

Проще говоря, рассматривайте регистры как просто значения, порядок их окончательного сохранения не важен.

Вы знаете, что при записи в eax вы пишете 32-битное число, и вы знаете, что при чтении из eaxвы будете читать то же самое 32-битное число.В этом смысле порядковый номер значения не имеет.

Чем вы знаете, что в «al» у вас есть менее значимая 8-битная часть значения, в «ah» наиболее значимая 8-битная часть младших 16биты.Невозможно получить доступ к одиночным байтам на старших 16 битах, за исключением, конечно, чтения всего 32-битного значения.

...