fix: немного расширил описание примера с inc

This commit is contained in:
Miheev Egor
2024-09-22 14:57:24 +03:00
parent 3e6a77c710
commit 0faffcd5c8

View File

@ -125,11 +125,13 @@ SIB байт состоит из 2 битов SS, которые предста
*Интересный факт, в качестве index не может использоваться rsp* *Интересный факт, в качестве index не может использоваться rsp*
Не буду много повторяться. Instruction `inc r/m16`. Opcode `FF /0`. `/0` означает, что в ModR/M в поле reg нужно записать 3 нуля. Остальное адрессуется как обычно, поэтому самое время обсудить вот какую вещь. Если нам необходимо опустить базу, то в SIB байте мы поставим в поле base 101. Однако для этого в mod нужно поставить 00 и автоматически придется записать 4 байта смещения. Не буду много повторяться. Внутри опокад стоит `WORD PTR`, что значит, что я самолично попросил ассемблер относиться к содержимому скобок, как к указателю на 1 машинное слово. Возможно также отнестись как к указателю на байт `BYTE`, двойное слово `DWORD` и четверное слово `QWORD`. Instruction `inc r/m16`. Opcode `FF /0`. `/0` означает, что в ModR/M в поле reg нужно записать 3 нуля. Остальное адрессуется как обычно, поэтому самое время обсудить вот какую вещь. Если нам необходимо опустить базу, то в SIB байте мы поставим в поле base 101. Однако для этого в mod нужно поставить 00 и автоматически придется записать 4 байта смещения.
[ 0110 0110 ] [ 1111 1111 ] [ 00 000 100 ] [ 01 110 101 ] [ 0001 1111 ] [ 0000 0000 ] [ 0000 0000 ] [ 0000 0000 ] [ 0110 0110 ] [ 1111 1111 ] [ 00 000 100 ] [ 01 110 101 ] [ 0001 1111 ] [ 0000 0000 ] [ 0000 0000 ] [ 0000 0000 ]
Замечу так же, что поскольку не используется ни REX.W ни один из расширенных регистров, REX байт принимал значение 0100 0000, но в таком случае спецификация Intel позволяет этот байт опускать. А вот что опускать нельзя - это префикс переназначения операнда, потому что используется 16 битный регистр. Ну а число для справке у нас в big endian Замечу так же, что поскольку не используется ни REX.W ни один из расширенных регистров, REX байт принимал значение 0100 0000, но в таком случае спецификация Intel позволяет этот байт опускать. А вот что опускать нельзя - это префикс переназначения операнда, потому что используется 16 битный регистр.
Число 31 у нас записано справа от SIB байта и у многих наверное появился вопрос, а почему оно выглядит имено так? А точнее - почему 3 последних байта заполнены нулями. Отвечаю - бог его знает и на самом деле, это зависит от процессора, и, возможно, от того, использует ли от little endian или big endian. Little endian - это когда число в памяти записывается как мы привыкли, то есть чем ливее циферка, тем она значительнее. Так что 0x1c1b так в память и запишутся - [ 0001 1100 ] [ 0001 1011 ]. Но вот в случае big endian запись идет по байтам, и если внутри байта все стандартно, то вот сами байты идут уже от младшего к старшему, поэтому то же число запишется уже в обратном порядке как [ 0001 1011 ] [ 0001 1100 ]. Думаю тут такая же фигня
Однако тут есть еще один важный момент Мы видим, что в данном случае есть один интересный момент. Вроде mod == 00, но тут 4 байта dispasement. Дело в том, что если mod == 00 а base == 101, то будет адресация вида index * scale + disp32. Довольно весело. Это я к чему? даже если вы знаете все номера регистры, таблицу смотреть все равно надо Однако тут есть еще один важный момент Мы видим, что в данном случае есть один интересный момент. Вроде mod == 00, но тут 4 байта dispasement. Дело в том, что если mod == 00 а base == 101, то будет адресация вида index * scale + disp32. Довольно весело. Это я к чему? даже если вы знаете все номера регистры, таблицу смотреть все равно надо