From 99b00ebcc05e1bc031ce20e3ae5160cd35460e7a Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Tue, 17 Sep 2024 16:10:47 +0300 Subject: [PATCH 01/21] =?UTF-8?q?feat(utils):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8F=20=D1=83=D1=82=D0=B8=D0=BB=D0=B8=D1=82=D0=B0=20hex?= =?UTF-8?q?2bin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Утилита hex2bin принимает в качестве аргумента из командной строки число в 16-ричной системе счисления, а возвращает число в 2-ичной это вспомогательная утилита для удобства сопоставления вывода radare2 и своим ответом --- 02-cpu-commnads/hex2bin.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 02-cpu-commnads/hex2bin.py diff --git a/02-cpu-commnads/hex2bin.py b/02-cpu-commnads/hex2bin.py new file mode 100755 index 0000000..55c6faf --- /dev/null +++ b/02-cpu-commnads/hex2bin.py @@ -0,0 +1,11 @@ +#!/usr/bin/python3 +import sys + +def hex2bin(hexNum: str) -> None: + return bin(int(hexNum, 16)) + +if (len(sys.argv) > 1): + print(hex2bin(sys.argv[1])) +else: + print("No number passed") + From 2f1c3787dd3f5671041e5decf2ba2f247608466c Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Tue, 17 Sep 2024 18:29:06 +0300 Subject: [PATCH 02/21] =?UTF-8?q?sync(README)[02]:=20=D0=B2=D0=BA=D0=B8?= =?UTF-8?q?=D0=BD=D1=83=D1=82=D0=BE=20=D0=BD=D0=B5=D0=BC=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BE=20=D0=BF=D1=80=D0=B5=D1=84=D1=84=D0=B8?= =?UTF-8?q?=D0=BA=D1=81=D1=83=20REX=20=D0=B8=20=D0=BD=D1=8B=D1=82=D1=8C?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=20=D0=B4=D1=80=D1=83=D0=B3=D0=B8=D0=BC=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B2=D0=BE=D0=B4=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index e502143..b81fcf0 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -2,3 +2,27 @@ ## Система команд процессора, ее связь с кодами команд +## Кодирование команд для x86-64 архитектуры + +Преподаватель на ресурсном курсе оставил огромный талмуд Intel на тему того, как кодируются команды у их процессоров. И пусть даже наш дорогой препод на лекции дал пояснения по конверсии и прочему, он оставил без ответа вопросы следующего толка: когда какие байты задействованы, где посмотреть опкоды команд и прочие мелочи жизни. Я тот еще программист, поэтому на меня тут не надейтесь, но помогу чем смогу + +Перво-наперво структура команды. Приведена она и у препода и в талмудике Intel, повторяться не хочу, но картинку оставлю + +![Структура команд](../assets/command_structure.png) + +На этой же картинке видно, что может быть от разное количество байт на КОП, на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике от Intel (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам Intel выглядят мягко скажем как-то так... + +![Пример таблицы опкода](../assets/opcode_table_example.png) + +Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... + +Пояснительную бригаду относительно суффиксов, префиксов, буковок и циферок, которые в табличке есть мы можем найти в начале (~44 страница). С вашего позволения я просто повторю то, что там написано с незанчительными комментариями + +- `REX.W` - Показывает, что REX префикс затрагивает размер операндов или меняет значение инструкции. Подробнее об этом они писали во второй главе. Учтите, что префиксы REX, которые повышают инструкции до работы с 64 битами не приводятся явно в колонке opcode. + +### Чутка про префикс REX + +Судя по всему, префикс REX стал почти обязателен при переходе на 64 разряда. Что ж, это не удивительно, так как в 64-разрядных системах прибавилось регистров, а их номера нужно где-то и как-то хранить, поэтому это вот такой вот "костылик". На самом деле в талмудике преведены схемы всех подключений, которые я пока не привожу, потому что это не самое главное, но может потом добавлю + +Вот что они пишут про префик REX во второй главе своего талмуда: "Префикс REX указывается не всегда в 64-разрядном режиме. Он необходим только тогда, когда инструкция адресуется к одному из рассширенных регистров или использует 64-разрядные операнды". То есть условно говоря если работам с 64 разрядами, то RAX нужен, а если нет - его может и не быть, если явно не сказано иное. Сами же REX - это 16 опкодов, которые берут пространство от 0x40 до 0x4F. В режиме режиме обратной совместимости и IA-32 отражают опкоды реальных инструкций, но нас естественно интересует режим 64 разрядов, а в нем они как отдельная инструкция не трактуются и идут только в связке. Также почему-то интел сокрушаются, что из-за этого однобайтовый опкод для инкреммента и декремента перестал существовать в 64 разрядных системах + From d5a00202e7d1c14b2f360b6dab11d27fe18b7afc Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 18:30:00 +0300 Subject: [PATCH 03/21] =?UTF-8?q?feat(utils):=20=D1=80=D0=B0=D1=81=D1=88?= =?UTF-8?q?=D0=B8=D1=80=D0=B5=D0=BD=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D0=BE=D0=BD=D0=B0=D0=BB=20hex2bin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Для удобства конструирования пайплайна появился флаг -s, при выставлении которого число читается со стандартного потока ввода, не в качества аргумента в консоли --- 02-cpu-commnads/hex2bin.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/02-cpu-commnads/hex2bin.py b/02-cpu-commnads/hex2bin.py index 55c6faf..6ac4acf 100755 --- a/02-cpu-commnads/hex2bin.py +++ b/02-cpu-commnads/hex2bin.py @@ -1,11 +1,18 @@ #!/usr/bin/python3 -import sys +import argparse def hex2bin(hexNum: str) -> None: return bin(int(hexNum, 16)) -if (len(sys.argv) > 1): - print(hex2bin(sys.argv[1])) -else: - print("No number passed") +parser = argparse.ArgumentParser(description="convert hex number to bin right in terminal") +parser.add_argument('-s', '--stdin', action='store_true', help="if passed takes input from terminal arguments") +parser.add_argument('number', nargs='?') + +args = parser.parse_args() +if args.stdin: + print(hex2bin(input())) +elif args.number: + print(hex2bin(args.number)) +else: + print("something went wrong") From c672fd4fcb21d7d4b786f0016c4e5127cae41611 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 21:32:24 +0300 Subject: [PATCH 04/21] =?UTF-8?q?fix:=20=D0=BF=D0=BE=D1=87=D0=B8=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D1=82=D0=BE=D0=B1=D0=B0=D1=80=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=B0=D1=80=D1=82=D0=B8=D0=BD=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index b81fcf0..160d29d 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -4,15 +4,15 @@ ## Кодирование команд для x86-64 архитектуры -Преподаватель на ресурсном курсе оставил огромный талмуд Intel на тему того, как кодируются команды у их процессоров. И пусть даже наш дорогой препод на лекции дал пояснения по конверсии и прочему, он оставил без ответа вопросы следующего толка: когда какие байты задействованы, где посмотреть опкоды команд и прочие мелочи жизни. Я тот еще программист, поэтому на меня тут не надейтесь, но помогу чем смогу +Преподаватель на ресурсном курсе оставил огромный талмуд Intel (далее именуемый "талмудик" и "талмуд") на тему того, как кодируются команды у их процессоров. И пусть даже наш дорогой препод на лекции дал пояснения по конверсии и прочему, он оставил без ответа вопросы следующего толка: когда какие байты задействованы, где посмотреть опкоды команд и прочие мелочи жизни. Я тот еще программист, поэтому на меня тут не надейтесь, но помогу чем смогу Перво-наперво структура команды. Приведена она и у препода и в талмудике Intel, повторяться не хочу, но картинку оставлю -![Структура команд](../assets/command_structure.png) +![Структура команд](assets/command_structure.png) На этой же картинке видно, что может быть от разное количество байт на КОП, на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике от Intel (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам Intel выглядят мягко скажем как-то так... -![Пример таблицы опкода](../assets/opcode_table_example.png) +![Пример таблицы опкода](assets/opcode_table_example.png) Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... From 9b7dada9822353c882bed91f537e3aa3bc555b12 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 21:34:11 +0300 Subject: [PATCH 05/21] =?UTF-8?q?fix:=20=D0=BF=D0=BE=D1=87=D0=B8=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D1=82=D0=BE=D0=B1=D0=B0=D1=80=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=B0=D1=80=D1=82=D0=B8=D0=BD=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 160d29d..ea1d052 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -8,11 +8,11 @@ Перво-наперво структура команды. Приведена она и у препода и в талмудике Intel, повторяться не хочу, но картинку оставлю -![Структура команд](assets/command_structure.png) +![Структура команд](/assets/command_structure.png) На этой же картинке видно, что может быть от разное количество байт на КОП, на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике от Intel (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам Intel выглядят мягко скажем как-то так... -![Пример таблицы опкода](assets/opcode_table_example.png) +![Пример таблицы опкода](/assets/opcode_table_example.png) Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... From 23bbc11bac6fc53363fe6b36a6d0a1e8467ac211 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 21:35:07 +0300 Subject: [PATCH 06/21] =?UTF-8?q?fix:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B7=D0=B0=D0=B1=D1=8B=D1=82=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=B8=D0=BD=D0=BA=D0=B8=20=D0=B2=20?= =?UTF-8?q?=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/REX_scheme.png | Bin 0 -> 9778 bytes assets/command_structure.png | Bin 0 -> 15918 bytes assets/opcode_table_example.png | Bin 0 -> 145775 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 assets/REX_scheme.png create mode 100755 assets/command_structure.png create mode 100755 assets/opcode_table_example.png diff --git a/assets/REX_scheme.png b/assets/REX_scheme.png new file mode 100755 index 0000000000000000000000000000000000000000..9dbcf1d385c8d59513326e99fec239d67b577561 GIT binary patch literal 9778 zcmc(FbyQT}yEiew00Rt2hckeH(x9}&5YmDmDcwj*H_S-4NC*NW4I(81N;4p(0!nvE zr*z(^kVO1p%Uzp@JsL zD=aLwE@gSdV;_^PX>TJ+?}h8VhAy_*DVTTK!g2GRqw?qRlz4eDM3Kl4Bn3(Us(?yL z)X!z<(63amjA4sfz7@@+I`sZ{Ea)lsBaOIaN)$o#OG}Z4`tOS6D18ETxCEAbEND4mccmz{e&hCy)A5VZ{gvKEc35|6bX9=Dn;4 z8K7Z5@1I5j;7H*5Q}g$$|J4ewx!x2m{YD=Ff-dd20@bwK{CxS-JGtu?P-xOu&z%`2 zo+q{P*H@QfqS-!;yY0mKHFin++VaDl02P_UWMqn7UbWTo2UZj}Zd94I;aEqN#sE_l z?t-IB&7k_!sE|mEEDSgOVFv32lJt`^mti)^o#BgUUS6 zh;_(iHSFa+LtE?szR$Zo|1)dUi{VJ82{Hzi0zB+f|K#}@b`sl~{SlR+G06_xow6jp zvLasDN6VKUSpUulD`?GjT>h9>Z<}F6-w!{ym)X771#qadxtt0-Ks=mvlLrPW+LFyi zV-CyYi!V@vdH%N_^O6is%0tm+d@qbA;ajnkpm&23cc{0tj$$I*_H=nQH|V~p+J*l}&!`gD1L zGku_V`)o|O|60O$I?$f}hjqylRRV`;1+{JRgcPpDc^3T8pE5*KIJR@84;#ylaM){) z<<6p-l=i@FQ<+Fwi1)6#zGTO3#K2t216OzNFzuK^yX{ihi!#=38kJ>ur0EBuom17j zie%k0euS%l>hLT*{1fUzn{M zq1o8TVaTzS3LB20`JDP(cQx~rB-fCv?WS)5HOJ=~ImZGzWc%IsZ5g6>-ogXumArP4`wce1jPlL)eX#()`T+81)q+fl;IiQ%d2u zplHVQ$N!4OMzyy8u_B~2APprw4;WsGX;TH4ETYOY;Zw$q63s)C_^E1wYn-7@HvS88 zq~?o+DS{O5p(_C}_aAe0T!tUIwYK}KE^z+LMnp}*+DB@B{Quo%eSw0o>EpsNy>dnF z=rplp1%7ZbXFfb##3j4>x2fb`j1!qjyx!`UzP=wp6>%Wc-`}s-OstbP{M7C8%#)NW zA^7@yw%2=ZP01yCac3uCXy`F%Jjcz7#{KAkV7G-1!ex%AQWV1ML6*4ZZqD_Eq5+G8 z{Qw%2kyFl9ra%+{#J>FzD3$10y5G3?T=b zXPKK}C7-Ll@1V ziNI1q@I#&W!HhJh);)f3cL>4^=ujB=J_a%8LkqHMh4W)_5$N%RN6qi%el8N5nwt9f z`?j@=`fT=6b*SgfO*XQ<&dTZwUpeP;)5t^#;m*o_Y47W`S5b8h(4uV@afWa#P~+o_uJbOrOaJI7gNe!2s!&i`0MSs_jLn*Peyu}%s!M9c z@oF8YE~qK|<0DD_Uker826v$@o!lMP%Tpz6T^!8Z+_)Sn2YtYbyBd+wfim)x$dua) zIkO>&h+WzVm_YL}m~r5CpU`uJnHazcZhFuz z{&1fdq3Po+_ChYO6Z{JqVT+a9<~CcfZHPten}AgLQ7+2ZyQnSSmU>2;EUnih zO?NY}x_8@E{pS6$FVu*{hDwRoxPI_@2afu>)sRqF7i+G+qUeX!_zK=N_|!zmOBt94 zgbedUs!eG!g#h8rWDv!9LU1f|tVv}=e^eU?UE-BbZ;*b>%R_$8T*Rv&EZ3>a^|`lW zL}e5~r$2(UBNU&2RIP_CHig`+32M7h10^nz9~#?fZdmME6>%C(@E2G-T5K6MC7TA@=6S zjdFFxE?t;Kg*XjygG8HjqeO159QlAXZS4h%O!stnlJNu!KR0cViR5l)6wA~^B2p$N z9!%y>EY)T|mck+9ElC{384NmJjn_;eraz)a$<*5}%$YL?6CzLBiW%NhoG!S03EOM7 zlk!QURiZ8Sw0O!Hh~7G9QJKPyaz zJO!6Cpi)j3g0e3mP7-S20gXeK&!d=d1uomA0ygQQPxl|rVtUj4R4X0sV?1CzVShR}Z3%nVr{X3qhqsaqWBt}i zr98RAwLy{(FHUIfKb{+y$DGV}Xmmf?9^*7|nSV77_FhBU7acOd{4+H~3w2h^A8VBJPNNyKfGmVXuuaJtJgP+mq>@%CztT*Z)$dUGKD- ze^Y|$qRM+xM?VQd+-`ipMAM>z$mzN?}c7?acOfDJV_iV zloR_+kHGHW|cDB%&HmGvU z5lXqq5HIYEs?rJY(DyL|HNK`u>h-i47W&-A=L5BG7TX}XC{Hu>Z=gr zjA@w5=L*d6jzr$<8Ie0tXW!s^Pm10IOG3M0ksH^MPvZb`xjt}wMjJa)@2fN2kJoAR z+^Eul`V?hzO3Zn5*Bi};xZ_5I`@i{>c19;M-3bBt#C=Y>%xS&r!|SXhUE|9I{V^tG z1O9Ycuvm7&RrnV<$y^Bx8e=ltlB*6!1Y-BLV(GLt3B~m34Mw+Z06taBWFm{*q@!n( zXV0(r!JCADIm`$o0W|E@pxt*HZc^ux`++-1^O=#Tb=*RMS%`*Kc zdUg=CNPawy6RgyQ(Lo(i@FSoS z@T>(RIr8KNFOiDZz35`B&fyC~18%SyRAoQuTxQ&1@4V6Ts7{pK+eWH-=BNX`m2$11 z(Qkp!MC>&gQ5uve(}7Yke-TzZ41{k;Inzf&HrAV~20?1N&?O$l>qxqjo>i)HU;Pc`xr%?7!aeQ62)_5T~BUg4QY-_}G7Iv)}(BD{cFTJvLf1Ds3xPD)~sR zd6hNinydV4ocw6dnKuDyThPYSCEUxBY-3hHqdtZ$P%g=>5Ol71nwyfD5I}EZ>cZ!9 zdfa|u{9S@%-PQlcZTZO2lJzNqFo!|T9 zt9mO-6@V04FytGsVtz_Yo@vh{D2HO>nOBq1ShgtJ0qu6asjZo2N63_6~nuOOe zbdBE=3zU2$Pfh#*K zrG7oLpy03^Z2;&T57V-6Tw492mY>sekp> zGBbA;|8jDj=oCO}<gE8xZvf+L`Enc7Jn@ZqNb>NVVF(k=`+V{C0<^mw5^kEkI>ByCgl0bKV1 zBUNnxT`jjf*V9f+N($XW<&h@~lGABZFQVrgVFep~!9`XD`Ysg+=z3h$vrg5nNll*w zNuK^Qor|#-rI#;5pAsFceCO=^=G)N8RXamgw_X)x{WyR?sg6v`M4q&t+gnaiJ-#}^6# z_I{4ia+=Sxh^ZF?mh%c(@j?$S8umZyoUKgvb0Rdas@Qb=!_l2sjw#z@H7oqQGGS|a z`E*EXTC{1D`yviHBS@jq4r~Y+u{aWRPL1E`}!#MV4d(%0dFdchDAz6^eVld#?{gW`YC9SDcnQpg|w-^BPEW- zilvtojao|ZIp;Sh<-(Uu*Lsgv_-kd|8F{Sp!$6<;3hl;Uh?8!X(Dp->R>WpcL+?(g z*Q2?g+ywTx;{oCDt-ynI3C3hWK}PTJ);1*C!JY5<^9Rf-%Q18PM^VSng_buC?ml79 zSvXbjX6O1VcS1b|%k8$QkORfHivv)5uWG*I(EjlYc|VadGTRGEK7lo+LHA7R?_h6V zj;xV&yomNTk>#aU^qbGS+-Ix0)5df;A{nr`;?SSZT4^j%6YTx&>TIZC*Id!`#7hOE ze43sAT^nDPRQJ${sBWI%QF;Syk_ikEteu%SH$%1&9cwCwMQNs|<=|6vUHlIrUg0t_ z-_{lM{YN`ghZ)(yWfg`9Gc->JDz}&H_`~f0&4cb7x~Igjxuh6fAl&yyua;tn9tBWp zV=mCqu`)85;4e~7<~5=?r+uklS<(E`R4lAG1MC*UOEFU0zlQzy%#+igwPUVV3oKWMPD zJUguSJ1niX+Fa^M9(!+_P;JG{!9noq)vI2uVITknAmh*PZ-VUY?SIGCs}Ih#w6*uX zip<_t6^i&1IMF%AkV$vDaF`6f7IRO0`7)n-t?7KbLBHB6s`_!@FbT3b@Z92bf4TQX z6<_lS&Ye4VfD$mPT)7C+|1v~Qz&>H2dS)T_rPLbDlQX;udw?gM@M3X%#PDB;4n$gL zQ6WKODD*llNC)$mK@c2E2+o-#1PScfACvs$H$OO50K9t44=#;IXbS!H#Cucj{cV$z z3_y&^k3GU;&S|9VRgY8Q1Aqa8jlS;5liXtYIU;LR-NVeC--!7d&Gyg4o;oYdHf(M> z{*G5sbL+!{%S$$Dj_23b?2`greiV{i9o4nay>l4M#akbKYg@DZVbnx!W8_`jh>oq& zxk=V#@ZqrD{L+%uvrLa*=4qGo3HHEg6TdaKAGe zXv>oHsjseLg-H{?Su0lZq*`2Y@$Fme>={!wJtCj(2K?n9f2HxHGAv(IXR zE)VrKCqDEod5X86oNZL7mj`DEIE--DJRR<}%ep54m&7TrFIP?Dr4@EeAN;f)iy|Of z*qz6)*Gcw(A&`#lBvy6jzLX8|!Jw3hO)7zY^)A*Zd8L~J!dx`zX$?9zp zq_l5DgDw#;ZBGU8v6C*%po#AU{%^`vMI=bK#m_y`#NQ`Np1Hc}dnvi>ov%n=kK0Yp zUSD}Po-D*X*vPLFNuA-XU-*=9Gmc(JR$l)3GYzv?#O|gUbjU)30rY*c&*YOw6bhAx zAMT-bd+l8SSGlUXdgr7|i&M=*aej@Adp&l>>It|6q}^2(M5s9+tXkZeEewt<{yFwb z8~@|SkNb{ccOXbx0u-9s5(*tB!^a+{|NmG{M#>aunIEnXGcq#j-t3BJ(hj--WbUjS zAV@3T)h)ln_0G07^G@chs>=OKPE?3v9FX*~vi@Guk>kHDX04onkg5F)WXP%o z@c|ri^LNIsEEdrUuT%sQUo2dfP++@94&=tVduc%s93Z6rf7Uej{CH<^3Mr z(jwefzP)*vCBA<}O-b3kp{lC792glL{Q^_4aJA|o?kgrK$pozKOX(52d;7vY(+%EL zUR#DWPLsMbx<*E2j?7PhL>{@pV0#$x^7&&-_m?m7z$oMUu@M9Wu4lGejY*R zM^3*b&U&NlaMf>rsmHqRPTWq*wTTH|Si32pxYdV%U3oF83POaued{n@J8BxtbbYxK zobv9>fD}_JeYvJl|7*Y5i7@rqdN*7k8s6Ag z?!7a!zno8pYi~gRqfkA0R5_uZWF!BMx5I5t&KI@>`I84nN5UB?w0CXP#;+JfU1bd3 z);Ujqs&;yB^HpnPT^So57E+@gjayCj{TM?DBsL$B2z;SXdXJ0$ojdfNgzMFXudjjl zuF8AR_stM<6=Od?Lsk^4@#0S;y}B-A_=z3}(858NnmUNcql{gI4h8$u)!xipTA zYo7||<$Y-I9jJl)?e~KX0VLl5IWVA^Tw#!CL&(`rN~`o9lwu21LzR@2G*i28@&l6Q z*gBMFvliw@rA#o_yTQr#B&OstC4CZRpDOcCmrFIFdblM_4bU_o0S$;?WaRH8^hn-0 z9aqF5!o#EHzJ*^)+!acD?{MA-+^eveK)up@iq*6n7?0R#-c!o1!CxUNaH40-5CFdq zx*eQ=-PBb!%Ge%@c)#1-*~9yL24xEV6qZw&b6X1MZmR>#j1w)mZwuw~I^Rz39rF0A z;|O_i2r2Xh{i<^N#cow`Ng$Z}B-icQ@xBb9?t@Xe&5Yg(JfAOTFH$1QX<`(4A9{uU z)-E0`s87v<-Zmn#qz@b&N_MdwOi%4JcrZg>gwoSqM?QM{ZT_UXq}%8&Sx;16rN#6D z(Ijtl!sI&zBIM8Ao8IM{!a@;J;mQ4?uYafzTz!gsT@SLyot0Zy#S?YaBg*V5OGBca zZ?W?#V_J_X1pL~tyJqtg;2iMVfaB%38J z<>RvN$UW&zGJ9Bx5|`RB-`}(zlWMUIbMk(7LWv3rM?YExt7Qq3XmiBNUXwOQ8vEgi zueHu@xSYhC!?~pc7@tUO#1@9$byGf0KMdm<+;9mFJx4E#1_TgGZA?*y-sOuLl{*Ug zhYR(?q3){^kufB4nIcz6{CRCxxZ?HL6C&jG)+g}sf$9R{FnG{2soJXMYeqiY4tbUp z4(E|%vbU5%$lBW0f97qoK5e}gXGxpZFfw_*8~#mc!cQZp!?aqE{?KAH@(w(yaJpb+K7}pMY2;v48~^rnd}!P> z|5=Be8!VIAJZ3)^>nj=U{CZ4(KTU>7@PdTAh^ox#I=SoNCF2SZf};5&c>CQBV9=By zb=ar4b1n_KRkE|Q#R6vV%Rjx^K`FB`B1tPscbEGYLR&`rc4-5RNU6SljM}9kJDE*W zx=X-5a&61z*R&Zr*tPsYRAdnLm7=*0v6KjaMHUtZfx}$c>3;p8OQCzP6Ui&5I>Z1t zIB4&B_cMbF+If0(@4*ez15*#(DH?m&1}4uEK2h>`_u12grOnKDeFWWJ_o%OBXUcJ@C(Nq3ymAf@aONpjCeBdR&-w@pyZt!{53@U{ z2%FD)dGEqfoBgNNER>HAZo9!!)_ejjYGDc`PcAZFc8l}i`P^Gx^!n(GIzYgSyRb~0 z%S6I}_%|u?;zp(~LyprfAtXcfpKf9A1bLDZD0+pu&+@tHaKOD!&FVeRD5WX0IxaeH z?#3BM8l7r;4p8T`zQkS|yPgwIW$Q5i`P0`&+8(dmwEuHRxy#}P)1=#6v_1u1TIF3X z;)Ww8%&C7$xnf~wf@(|qxAU;>o3A6kL>I^iMFY|K>6oBlfn~d}^ zYkJEZ1n7qQBvmjcOtS#Y?Avz9$*n+~?=4et<1i%z+(gE`{z9hwoKSm4ql@re%`Vot z*13h<1eSae3{kZ$SQwlhs{KT&eSm6({};+lv|xC?H`Yo`if<-$-tW1@nBW~kR77wL zQ_;7WJ{;$-aa~>h`k;~Do{Qzx_Jm5TPw;K6AD_*X+WE^Gk4zcKQFCuIR|Le0xok`t zLq8TG(Pm;ZutxF%sH=zsom;X-uDnl(F{{Py+PCCoM50clYD`4#bt2`#&H&R5zQ5(+ z&z(mTuVLe2OKwPnYdvtz3rktyp?tZl8S>u%sbuVk literal 0 HcmV?d00001 diff --git a/assets/command_structure.png b/assets/command_structure.png new file mode 100755 index 0000000000000000000000000000000000000000..8d3284d57494e061012e3a009a7cb783e933aad5 GIT binary patch literal 15918 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 literal 0 HcmV?d00001 diff --git a/assets/opcode_table_example.png b/assets/opcode_table_example.png new file mode 100755 index 0000000000000000000000000000000000000000..11437aabb9bb37a3aa1bd249762fb8565a18b30a GIT binary patch literal 145775 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­5*vE46$mf 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 literal 0 HcmV?d00001 From 5bd7ad95b3a97b19f493165f532ec10dfbb07515 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 21:35:54 +0300 Subject: [PATCH 07/21] =?UTF-8?q?fix:=20=D0=B2=D0=B5=D1=80=D0=BD=D1=83?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=B0=D0=BA=20=D0=B1=D1=8B=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index ea1d052..f8a0042 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -8,11 +8,11 @@ Перво-наперво структура команды. Приведена она и у препода и в талмудике Intel, повторяться не хочу, но картинку оставлю -![Структура команд](/assets/command_structure.png) +![Структура команд](../assets/command_structure.png) На этой же картинке видно, что может быть от разное количество байт на КОП, на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике от Intel (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам Intel выглядят мягко скажем как-то так... -![Пример таблицы опкода](/assets/opcode_table_example.png) +![Пример таблицы опкода](../assets/opcode_table_example.png) Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... From aa38e902ae016e52ee9a1cdeb4dcc9a5e6952d1f Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 22:14:13 +0300 Subject: [PATCH 08/21] =?UTF-8?q?feat:=20=D1=80=D0=B0=D1=81=D0=BA=D1=80?= =?UTF-8?q?=D1=8B=D1=82=D1=8B=20=D0=BE=D0=B1=D0=BE=D0=B7=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=82=D0=B0=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D1=86=D0=B5=20=D0=BE=D1=82=20intel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index f8a0042..1259ced 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -16,9 +16,17 @@ Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... -Пояснительную бригаду относительно суффиксов, префиксов, буковок и циферок, которые в табличке есть мы можем найти в начале (~44 страница). С вашего позволения я просто повторю то, что там написано с незанчительными комментариями +В общем я тут свои пояснения ко всему, что указывают сами Intel, но по простяге и на основе опыта ручного ассемблирования (который к слову не очень богат, потому что я еще не успел настолько сойти с ума, чтобы делать работу ассемблера за него) -- `REX.W` - Показывает, что REX префикс затрагивает размер операндов или меняет значение инструкции. Подробнее об этом они писали во второй главе. Учтите, что префиксы REX, которые повышают инструкции до работы с 64 битами не приводятся явно в колонке opcode. +- `REX.W` - По идее этот префикс может означать много вещей, но на практике пока что я сталкивался с ним только в таком разрезе: если он есть в начале, значит в REX-байте нужно поставить единичку в 3 разряде (4-я цифра справа). Также это означает, что данный байт вообще говоря обязателен для функционирования этой команды + +- `REX` - Такое встречается на моей памяти только рядом с восьмибитными инструкциями и всегда только для того, чтобы к ним тут же приложилось пояснение от intel, что какие-то там проблемы. В общем читайте все это в сносках, потому что сам по себе флаг обозначает простое наличие REX-байта перед опкодом по всей видимости +- `/digit` - можно порой встретить что-то типа `/0` или `/7`. Когда такое видите, это значит, что в ModR/M байте вместо поля reg нужно записать 2 запись числа, которое после слеша. То есть от `000` и до `111`. А все остальное адресуете как раньше +- `/r` - указывает на то, что в ModR/M байте все поля Mod, Reg и R/M используются в стандартном варианте +- `cb`, `cw`, `cd`, `cp`, `co`, `ct` - сам плохо понимаю, что это за покемоны такие. В 64-битных опкодах встречаются редко. Согласно мануалу показывают, сколько битов после опкода следует зарезервировать под смещение для сегмента кода (если вы откроете методичку мелицины, то это тот самый CS или Code Segment). Также согласно мануалу иногда оно может переназначить новое значение сегментному регистру кода. Возможны варианты 1 байт, 2 байта, 4 байта, 6 байт, 8 байт, 10 байт соотвественно. +- `ib`, `iw`, `id`, `io` - Показывают, что после опкода, ModR/M байта (если есть) должен идти непосредственный операнд длиной 1, 2, 4, 8 байт соответственно. Встречается он в таблице обычно там же, где в колонке instruction в соответствующем месте производятся какие-то действия с непосредственными операндами. При чем надо понимать, что нельзя просто опустить байты, которые заполнены нулями, даже если очень хочется и мама разрешила. ставим столько, сколько требует спецификация +- `+rb`, `+rw`, `+rd`, `+ro` - встречается тогда, когда создатели процессора почему-то решили засунуть регистр прям в опкод операнда. Ну, не нам их за это судить. Фактически нам нужно просто глянуть в таблицу которая приведена самими интелами, чтобы определиться только с тем, какое число от 0 до 7 прибавлять. В целом это число является номером регистра, а идут они всегда в следующем порядке: rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, а также дополнительные регистры r8-r15 работают в том же режиме, то есть начинают нумероваться с нуля. Единственное отличие - бит в REX байте нужно поставить. А вообще табличка должен сказать весьма любопытная, поэтому с ней придется ознакомиться самому. Находится она на 45 странице руководства. +- `+i` - используется в операциях с плавающей точкой. Такие операции любят использовать стек сопроцессора (потому что на самом деле вся арифметика с плавающей точкой аппаратно ускоряется и у нее тоже есть собственная память). Так вот, такое стек обозначается ST(i). Где ST(0) - вершина стека. Не берусь утверждать, но по всей видимости в стеке всего 8 ячеек, потому что по мануалу i может принимать значения от 0 до 7. Соотвественно наша задача просто прибавить это число к байту слева от плюса и на этом все. Больше ничего не требуется ### Чутка про префикс REX From bfde784868d53cb3414dadc4324439f56bc380ee Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 22:27:26 +0300 Subject: [PATCH 09/21] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=B5=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D1=8F=D1=82=D0=BD=D1=8B=D0=B5=20=D0=BE=D0=BF=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D1=82=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 1259ced..174d7a0 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -10,23 +10,23 @@ ![Структура команд](../assets/command_structure.png) -На этой же картинке видно, что может быть от разное количество байт на КОП, на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике от Intel (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам Intel выглядят мягко скажем как-то так... +На этой же картинке видно, что может быть от разное количество байт на КОП (который я по привычке именую опкодом), на Displacement, на Immediate и прочем. Да и еще проскакивают надписи `(if required)` и `(optional)`. Вопрос назревает сам собой - а где смотреть-то. И ответ у меня к сожалению не утешительный - в том самом великом и ужасном талмудике (по крайней мере я не нашел другого способа понадежнее). Но тут есть одна так сказать проблемка... Таблички по командам от Intel выглядят мягко скажем как-то так... ![Пример таблицы опкода](../assets/opcode_table_example.png) Хтонь лично на мой взгляд довольно неприятная, но на самом деле она не так страшна, как вы подумали... Она значительно хуже... -В общем я тут свои пояснения ко всему, что указывают сами Intel, но по простяге и на основе опыта ручного ассемблирования (который к слову не очень богат, потому что я еще не успел настолько сойти с ума, чтобы делать работу ассемблера за него) +В общем я тут приведу свои пояснения ко всему, что указывают сами Intel, но не в сухую по руководству, а на основе собственного опыта ручного ассемблирования (который, к слову, не очень богат, потому что я еще не успел настолько сойти с ума, чтобы делать работу ассемблера за него) -- `REX.W` - По идее этот префикс может означать много вещей, но на практике пока что я сталкивался с ним только в таком разрезе: если он есть в начале, значит в REX-байте нужно поставить единичку в 3 разряде (4-я цифра справа). Также это означает, что данный байт вообще говоря обязателен для функционирования этой команды +- `REX.W` - По идее этот префикс может означать много вещей, но на практике пока что я сталкивался с ним только в таком разрезе: если он есть в начале, значит в REX-байте нужно поставить единичку в 3 разряде (4-я цифра справа). Также это означает, что данный байт, вообще говоря, обязателен для функционирования этой команды -- `REX` - Такое встречается на моей памяти только рядом с восьмибитными инструкциями и всегда только для того, чтобы к ним тут же приложилось пояснение от intel, что какие-то там проблемы. В общем читайте все это в сносках, потому что сам по себе флаг обозначает простое наличие REX-байта перед опкодом по всей видимости -- `/digit` - можно порой встретить что-то типа `/0` или `/7`. Когда такое видите, это значит, что в ModR/M байте вместо поля reg нужно записать 2 запись числа, которое после слеша. То есть от `000` и до `111`. А все остальное адресуете как раньше +- `REX` - Такое встречается, на моей памяти, только рядом с восьмибитными инструкциями и всегда только для того, чтобы к ним тут же приложилось пояснение от intel, что какие-то там проблемы. В общем читайте все это в сносках, потому что сам по себе флаг означает простое наличие REX-байта перед опкодом по всей видимости +- `/digit` - можно порой встретить что-то типа `/0` или `/7`. Когда такое видите, это значит, что в ModR/M байте вместо поля reg нужно записать в двоичной системе то число, которое после слеша. То есть от `000` и до `111`. А все остальное адресуете как раньше - `/r` - указывает на то, что в ModR/M байте все поля Mod, Reg и R/M используются в стандартном варианте -- `cb`, `cw`, `cd`, `cp`, `co`, `ct` - сам плохо понимаю, что это за покемоны такие. В 64-битных опкодах встречаются редко. Согласно мануалу показывают, сколько битов после опкода следует зарезервировать под смещение для сегмента кода (если вы откроете методичку мелицины, то это тот самый CS или Code Segment). Также согласно мануалу иногда оно может переназначить новое значение сегментному регистру кода. Возможны варианты 1 байт, 2 байта, 4 байта, 6 байт, 8 байт, 10 байт соотвественно. +- `cb`, `cw`, `cd`, `cp`, `co`, `ct` - сам плохо понимаю, что это за покемоны такие. В 64-битных опкодах встречаются редко. Согласно мануалу показывают, сколько битов после опкода следует зарезервировать под смещение для сегмента кода (если вы откроете методичку Милицина, то это тот самый CS или Code Segment). Также согласно талмудику иногда оно может изменить значение сегментному регистру кода. Возможны варианты 1 байт, 2 байта, 4 байта, 6 байт, 8 байт, 10 байт соотвественно. - `ib`, `iw`, `id`, `io` - Показывают, что после опкода, ModR/M байта (если есть) должен идти непосредственный операнд длиной 1, 2, 4, 8 байт соответственно. Встречается он в таблице обычно там же, где в колонке instruction в соответствующем месте производятся какие-то действия с непосредственными операндами. При чем надо понимать, что нельзя просто опустить байты, которые заполнены нулями, даже если очень хочется и мама разрешила. ставим столько, сколько требует спецификация -- `+rb`, `+rw`, `+rd`, `+ro` - встречается тогда, когда создатели процессора почему-то решили засунуть регистр прям в опкод операнда. Ну, не нам их за это судить. Фактически нам нужно просто глянуть в таблицу которая приведена самими интелами, чтобы определиться только с тем, какое число от 0 до 7 прибавлять. В целом это число является номером регистра, а идут они всегда в следующем порядке: rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, а также дополнительные регистры r8-r15 работают в том же режиме, то есть начинают нумероваться с нуля. Единственное отличие - бит в REX байте нужно поставить. А вообще табличка должен сказать весьма любопытная, поэтому с ней придется ознакомиться самому. Находится она на 45 странице руководства. -- `+i` - используется в операциях с плавающей точкой. Такие операции любят использовать стек сопроцессора (потому что на самом деле вся арифметика с плавающей точкой аппаратно ускоряется и у нее тоже есть собственная память). Так вот, такое стек обозначается ST(i). Где ST(0) - вершина стека. Не берусь утверждать, но по всей видимости в стеке всего 8 ячеек, потому что по мануалу i может принимать значения от 0 до 7. Соотвественно наша задача просто прибавить это число к байту слева от плюса и на этом все. Больше ничего не требуется +- `+rb`, `+rw`, `+rd`, `+ro` - встречается тогда, когда создатели процессора почему-то решили засунуть регистр прям в опкод операнда. Ну, не нам их за это судить. Фактически нам нужно просто глянуть в таблицу которая приведена самими Intel, чтобы определиться только с тем, какое число от 0 до 7 прибавлять. В целом это число является номером регистра, а идут они всегда в следующем порядке: rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, а также дополнительные регистры r8-r15 работают в том же режиме, то есть начинают нумероваться с нуля. Единственное отличие - бит в REX байте нужно поставить. А вообще табличка должен сказать весьма любопытная, поэтому с ней придется ознакомиться самому. Находится она на 45 странице руководства. +- `+i` - используется в операциях с плавающей точкой. Такие операции любят использовать стек сопроцессора (потому что на самом деле вся арифметика с плавающей точкой аппаратно ускоряется и у нее тоже есть собственная память). Так вот, такой стек обозначается ST(i). Где ST(0) - вершина стека. Не берусь утверждать, но по всей видимости в стеке всего 8 ячеек, потому что по мануалу i может принимать значения от 0 до 7. Соотвественно наша задача просто прибавить это число к байту слева от плюса и на этом все. Больше ничего не требуется ### Чутка про префикс REX From b97816df1568800268ca4ba1140be9b4000df1ce Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 23:20:56 +0300 Subject: [PATCH 10/21] =?UTF-8?q?feat:=20=D0=BF=D1=80=D0=B8=D0=B2=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BD=D0=B0=20=D0=B8=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Это вряд ли исчерпывающее руководство как собирать инструкции, но оно подходит для сборки самых разных инструкций только чтением методички от intel --- 02-cpu-commnads/README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 174d7a0..8ab42ec 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -28,9 +28,35 @@ - `+rb`, `+rw`, `+rd`, `+ro` - встречается тогда, когда создатели процессора почему-то решили засунуть регистр прям в опкод операнда. Ну, не нам их за это судить. Фактически нам нужно просто глянуть в таблицу которая приведена самими Intel, чтобы определиться только с тем, какое число от 0 до 7 прибавлять. В целом это число является номером регистра, а идут они всегда в следующем порядке: rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, а также дополнительные регистры r8-r15 работают в том же режиме, то есть начинают нумероваться с нуля. Единственное отличие - бит в REX байте нужно поставить. А вообще табличка должен сказать весьма любопытная, поэтому с ней придется ознакомиться самому. Находится она на 45 странице руководства. - `+i` - используется в операциях с плавающей точкой. Такие операции любят использовать стек сопроцессора (потому что на самом деле вся арифметика с плавающей точкой аппаратно ускоряется и у нее тоже есть собственная память). Так вот, такой стек обозначается ST(i). Где ST(0) - вершина стека. Не берусь утверждать, но по всей видимости в стеке всего 8 ячеек, потому что по мануалу i может принимать значения от 0 до 7. Соотвественно наша задача просто прибавить это число к байту слева от плюса и на этом все. Больше ничего не требуется +## Как собрать ~~своего покемона~~ свою команду из ассемблера + +*оно же: "Да как этой б\*\*\*ской таблицей пользоаться вообще* + +![Структура команд](../assets/command_structure.png) + +Повторно привожу это изображение, так как оно нам еще понадобится + +Самое важное чиселко, которое тут есть - 16-ричное породы "понятно-написанное". Оно - фундамент всего опкода, его мы и берем. А дальше алгоритм следующий: + +1. Смотрим, колонку instruction. В ней ищем глазами базу и венец - понятно написанный опкод (это будет скорее всего от двух и до шести 16-ричных цифр). Дальше смотрим, надо ли к нему непосредственно что-то прибавать, и если надо - прибавляем. Ура - мы получили opcode. +2. Как только мы получили опкод, начинаем смотреть налево - если есть приписка REX.W, значит пишем REX байт. Пока что просто ставим заглушку: 0b01001000 или 0x48. Он нам потребуется если мы захотим адресоваться к регистрам с r8 по r15, а до тех пор он будет в заглушечном состоянии +3. Далее присматриваемся, надо ли что-то прорезервировать (те самые `cb`) и если непосредственно после опкода ничего не требуется начинаем писать ModR/M байтx +4. Написание ModR/M байта пожалуй самый запутанный процесс, но с ним нам должна помочь табличка от Intel. Находятся они в районе 32-34 страниц. Но расскажу так. Поля у ModR/M следующие - 2 битовый mod, потом 3 битный reg, потом 3 битный r/m. + 1. mod - указывает на то, как будет адресоваться r/m (третье поле). r/m - сокращение от register/memory. То есть как можно из названия догадаться, только в этом поле процессор может адресовать память компьютера. Это же и есть фундаментальная причина, по которой нельзя заассемблировать команду вроде `mov [addr1], [addr2]`. Возможное содержимое этого поля такого: `00` - Будет адресоваться оперативная память, при чем использоваться будут только регистры (`mov rax, [rdi + rsi*4]`). `01` - будет адресоваться оперативная память и помимо регистра будет еще и смещение, но длиной не больше 1 байта (`add [rbp + rcx - 2], rax`). `10` - то же, что и `01`, но смещение уже занимает 4 байта. `11` - адресоваться будут 2 регистра (`xor rax, rbx`). Если мы поставили что угодно кроме `11` - это надо запомнить, потому что число которое мы записали нужно будет включить в двоичный вид команды использовав взятое нами число байт, а разместить их надо будет либо после ModR/M, либо после SIB байта, если последний будет. + 2. reg - указывает регистр, если в колонке opcode не стоит что-то из разряда `/4`. Если стоит, то в reg записывается это число в двоичной форме. Все неиспользованные разряды заполняются нулями. Если длина регистра не вмещается, то самую старшую единицу можно поставить в REX.R + 3. R/M - указывает регистр или участок в памяти, который будет адрессоваться. Можем писать сюда номер любого регистра (если не влезет, то расширять его при помощи X бита в REX байте). Однако особенностью тут обладает значение `100`, потому что оно показывает процессору, что нужен SIB байт. При любом другом значении адрес (если mod != 0b11) будет взят из регистра и если есть смещение, оно будет добавлено к значению этого адреса. Единственное, что если mod взят 0b00, то значение 101 тоже магическое - оно затребует 32-битное смещение и использует его в качестве адреса (это точно сработает в 32 битном режиме, но не уверен, что сработает в 64 битах) +5. Если вы взяли такую комбинацию, что вам понадобился SIB байт (а это mod != 11, r/m == 100), то разберемся со структурой байта. Весь этот байт завязан исключительно на адресацию в памяти и состоит из трех побей Scale (SS) в 2 бита, index в 3 бита, base и 3 бита. для разбора полей возьмем следующий пример `[rbx + rcx * 4 + 3]` + 1. SS - это scale - это то, на что будет умножаться регистр индекса, при чем это двухбитовое число можно считать степенью двойки. То есть получается 2^(SS) - это коэфициент на который мы умножаем и можем получается умножить на 1, 2, 4 и 8. + 2. index - это регистр, который будет умножаться на 2^(SS). Если вы хотите вписать регистры с r8-r15, то невлезающую единицу можно записать в REX.X. В целом же связка SS и index и обеспечивает наличие в адресе в нашем примере `rcx * 4` + 3. base - указывает на регистр, значение которого в лоб прибавится к адресу, то есть в нашем примере он отвечает за `rbx`. Если базовый регистр не нужен, на его место ставится `101` + +6. После SIB идет displacement байты (1 или 4 в зависимости от поля mod в ModR/M). Заполняем их согласно выделенному количеству +7. После dispacement идет immediate байты - они могут встретиться если в табличке в колонке opcode на этой строке есть что-то похожее на `ib` или другие, которые мы упоминали. заполняем сколько надо + + From 3ff51630f5e3069ea9a5dd864d28cf0aebd073d7 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Wed, 18 Sep 2024 23:41:20 +0300 Subject: [PATCH 11/21] =?UTF-8?q?fix:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=87=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=20=D0=B8=D0=BD=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=86=D0=B8=D0=B8=20=D0=BF=D0=BE=20=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 8ab42ec..35f5309 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -53,6 +53,13 @@ 6. После SIB идет displacement байты (1 или 4 в зависимости от поля mod в ModR/M). Заполняем их согласно выделенному количеству 7. После dispacement идет immediate байты - они могут встретиться если в табличке в колонке opcode на этой строке есть что-то похожее на `ib` или другие, которые мы упоминали. заполняем сколько надо +NOTE: По какой-то причине это не указано в руководстве Intel, но по крайней мере если верить сайту, который я использовал для ассемблирования инструкций, то нужно обязательно учитыать префиксы к опкоду прежде чем начинать кодировать (опять же все по опыту): + +1. `0x67` - ставится если команда **адресуется** при помощи 32-битных регистров +2. `0x66` - ставится, если программа иссользует хотя бы 1 16-битный регистр + +Благо для 8-битных операций другие опкоды и хотя бы на них не надо префиксы запоминать) + + +*Обозначений в этой колонке кратно больше, но я буду стараться приводить их кратко. поскольку тут есть регистры на любой вкус и цвет, я буду ставить символ # когда на месте # может быть число от 16 до 64* + +- `rel#` - относительный адрес. Обычно с ним связана адресация относительно rip, а вернее относительно по всей видимости следующего его положения. Тут надо смотреть визасемблированый код. Встречается эта красота когда мы адресуемся относительно меток в ассемблере. Под капотом же по словам талмудика это число засовывается в байты после опкода как знаковое число и прибавляется к содержимому rip. Пути ассемблера неисповедимы, поэтому я рад, что вручную считать где именно в памяти что лежит нам не надо +- `r#` - бозначает регистр размером # битов (от 8-битных до 64-битных) +- `m#` - обозначает ячейку памяти размером # бит. периодически можено даже встретить # равное 128, что используется только в SSE и SSE2 инструкциях +- `r/m#` - показывает, что операнд или память (например `[r11 + rcx + 2]`), или регистр (например `rcx`). Если относиться как к памяти, то число `#` указывает не на то, как память адресуется, а сколько битов будет из памяти прочитано, А если как к регистру, то нужно выбирать регистр по размеру, иначе процессор будет жаловаться +- `imm#` - тут `#` может принимать помимо стандартных еще и значение 8. обозначает, что работа ведется с непосредственным операндом (как например в инструкции `mov rax, 12`) +- `moffs#` - сокращение от memory offset - весьма любопытно. Показывает, что программа не использует ModR/M байт. Встречается только в некоторых вариациях `mov`, а адрес задается в качестве смещения относительно базового сегмента (не уверен, что это означает, но думаю относительно сегмента, где сейчас находится rip) +- `Sreg` - указывает на использование сегментного регистра. Битовые присвоения для сегментных регистров таковы: e ES = 0, CS = 1, SS = 2, DS = 3, FS = 4, и GS = 5 + +Остальные инструкции здесь не привожу, поскольку они затрагивают работу с числами с плавающей точкой, векторами и прочими радостями, до которых надеюсь не дойдет + ## Как собрать ~~своего покемона~~ свою команду из ассемблера *оно же: "Да как этой б\*\*\*ской таблицей пользоаться вообще* ![Структура команд](../assets/command_structure.png) -Повторно привожу это изображение, так как оно нам еще понадобится +Повторно привожу это изображение. Оно показывает общую структуру команды для процессора. Далее в инструкции я буду обращаться к разным участкам этой команды применяя соответствующие обозначения. Для примера команды можете смотреть на табличку для add в качестве примера того, что можно там увидеть Самое важное чиселко, которое тут есть - 16-ричное породы "понятно-написанное". Оно - фундамент всего опкода, его мы и берем. А дальше алгоритм следующий: 1. Смотрим, колонку instruction. В ней ищем глазами базу и венец - понятно написанный опкод (это будет скорее всего от двух и до шести 16-ричных цифр). Дальше смотрим, надо ли к нему непосредственно что-то прибавать, и если надо - прибавляем. Ура - мы получили opcode. -2. Как только мы получили опкод, начинаем смотреть налево - если есть приписка REX.W, значит пишем REX байт. Пока что просто ставим заглушку: 0b01001000 или 0x48. Он нам потребуется если мы захотим адресоваться к регистрам с r8 по r15, а до тех пор он будет в заглушечном состоянии -3. Далее присматриваемся, надо ли что-то прорезервировать (те самые `cb`) и если непосредственно после опкода ничего не требуется начинаем писать ModR/M байтx +2. Как только мы получили опкод, начинаем смотреть налево - если есть приписка REX.W, значит пишем REX байт. Пока что просто ставим заглушку: 0b01001000 или 0x48. Он нам потребуется если мы захотим адресоваться к регистрам с r8 по r15, а до тех пор он будет в заглушечном состоянии. На будущее также отмечу, что выглядит этот байт в общем случае примерно так - 0100 WRXB, где 0100 - обязательная часть, а все к остальным битам я буду адресоваться через точку +3. Далее присматриваемся, надо ли что-то прорезервировать (те самые `cb`) и если непосредственно после опкода ничего не требуется начинаем писать ModR/M байт 4. Написание ModR/M байта пожалуй самый запутанный процесс, но с ним нам должна помочь табличка от Intel. Находятся они в районе 32-34 страниц. Но расскажу так. Поля у ModR/M следующие - 2 битовый mod, потом 3 битный reg, потом 3 битный r/m. 1. mod - указывает на то, как будет адресоваться r/m (третье поле). r/m - сокращение от register/memory. То есть как можно из названия догадаться, только в этом поле процессор может адресовать память компьютера. Это же и есть фундаментальная причина, по которой нельзя заассемблировать команду вроде `mov [addr1], [addr2]`. Возможное содержимое этого поля такого: `00` - Будет адресоваться оперативная память, при чем использоваться будут только регистры (`mov rax, [rdi + rsi*4]`). `01` - будет адресоваться оперативная память и помимо регистра будет еще и смещение, но длиной не больше 1 байта (`add [rbp + rcx - 2], rax`). `10` - то же, что и `01`, но смещение уже занимает 4 байта. `11` - адресоваться будут 2 регистра (`xor rax, rbx`). Если мы поставили что угодно кроме `11` - это надо запомнить, потому что число которое мы записали нужно будет включить в двоичный вид команды использовав взятое нами число байт, а разместить их надо будет либо после ModR/M, либо после SIB байта, если последний будет. 2. reg - указывает регистр, если в колонке opcode не стоит что-то из разряда `/4`. Если стоит, то в reg записывается это число в двоичной форме. Все неиспользованные разряды заполняются нулями. Если длина регистра не вмещается, то самую старшую единицу можно поставить в REX.R From e14b35c2f3de7baab63c0c6f905e3b79e473368b Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Thu, 19 Sep 2024 13:41:27 +0300 Subject: [PATCH 13/21] =?UTF-8?q?fix:=20=D1=80=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D0=B0=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BA=D0=BE=D0=BB?= =?UTF-8?q?=D0=BE=D0=BD=D0=BA=D0=B5=20instruction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 9f794fd..34906ea 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -41,7 +41,7 @@ - `m#` - обозначает ячейку памяти размером # бит. периодически можено даже встретить # равное 128, что используется только в SSE и SSE2 инструкциях - `r/m#` - показывает, что операнд или память (например `[r11 + rcx + 2]`), или регистр (например `rcx`). Если относиться как к памяти, то число `#` указывает не на то, как память адресуется, а сколько битов будет из памяти прочитано, А если как к регистру, то нужно выбирать регистр по размеру, иначе процессор будет жаловаться - `imm#` - тут `#` может принимать помимо стандартных еще и значение 8. обозначает, что работа ведется с непосредственным операндом (как например в инструкции `mov rax, 12`) -- `moffs#` - сокращение от memory offset - весьма любопытно. Показывает, что программа не использует ModR/M байт. Встречается только в некоторых вариациях `mov`, а адрес задается в качестве смещения относительно базового сегмента (не уверен, что это означает, но думаю относительно сегмента, где сейчас находится rip) +- `moffs#` - сокращение от memory offset - весьма любопытно. Показывает, что программа не использует ModR/M байт. Встречается только в некоторых вариациях `mov`, а адрес задается в качестве смещения относительно базового сегмента (не уверен, что это означает, но думаю относительно сегмента, где сейчас находится rip). Сами интел например на `mov al, moffs8` пишет следующее описание *"Move byte at (seg:offset) to A"*. Также надо понимать, что # задает лишь сколько байтов будет прочитано, а offset задается вполне себе 4 байтами после опкода - `Sreg` - указывает на использование сегментного регистра. Битовые присвоения для сегментных регистров таковы: e ES = 0, CS = 1, SS = 2, DS = 3, FS = 4, и GS = 5 Остальные инструкции здесь не привожу, поскольку они затрагивают работу с числами с плавающей точкой, векторами и прочими радостями, до которых надеюсь не дойдет From 1e09eb6b967e8b34a66b2944a357f889fd25d9ae Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Thu, 19 Sep 2024 13:53:42 +0300 Subject: [PATCH 14/21] =?UTF-8?q?fix:=20=D0=BF=D0=BE=D0=B4=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B3=D1=80=D0=B0=D1=84=D1=83=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=20rel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 34906ea..701f547 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -36,7 +36,8 @@ *Обозначений в этой колонке кратно больше, но я буду стараться приводить их кратко. поскольку тут есть регистры на любой вкус и цвет, я буду ставить символ # когда на месте # может быть число от 16 до 64* -- `rel#` - относительный адрес. Обычно с ним связана адресация относительно rip, а вернее относительно по всей видимости следующего его положения. Тут надо смотреть визасемблированый код. Встречается эта красота когда мы адресуемся относительно меток в ассемблере. Под капотом же по словам талмудика это число засовывается в байты после опкода как знаковое число и прибавляется к содержимому rip. Пути ассемблера неисповедимы, поэтому я рад, что вручную считать где именно в памяти что лежит нам не надо +- `rel8` - адресация относитльно rip насколько я понимаю. Воспринимается как знаковое число длиной 8 бит, которое прибавится к содержимому rip +- `rel#` - адресация внутри одного сегмента кода (когда в ассемблере начинается `section .text` - это оно). Встречается обычно когда надо обратиться к меткам при прыжках туда и сюда, а оттого встретить можно в `j*` и `call`. Разбиратьсят точнее у меня к сожалению нет возможности - `r#` - бозначает регистр размером # битов (от 8-битных до 64-битных) - `m#` - обозначает ячейку памяти размером # бит. периодически можено даже встретить # равное 128, что используется только в SSE и SSE2 инструкциях - `r/m#` - показывает, что операнд или память (например `[r11 + rcx + 2]`), или регистр (например `rcx`). Если относиться как к памяти, то число `#` указывает не на то, как память адресуется, а сколько битов будет из памяти прочитано, А если как к регистру, то нужно выбирать регистр по размеру, иначе процессор будет жаловаться From 995260cdde1e05cabb95a33c2fba6e99515e0668 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Sep 2024 13:33:21 +0300 Subject: [PATCH 15/21] =?UTF-8?q?sync(README):=20=D0=BD=D0=B0=D1=87=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D1=8B=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BB=D0=B0=D0=B1=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 701f547..c24df14 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -74,11 +74,29 @@ NOTE: По какой-то причине это не указано в руководстве Intel, но по крайней мере если верить сайту, который я использовал для ассемблирования инструкций, то нужно обязательно учитыать префиксы к опкоду прежде чем начинать кодировать (опять же все по опыту): -1. `0x67` - ставится если команда **адресуется** при помощи 32-битных регистров -2. `0x66` - ставится, если программа иссользует хотя бы 1 16-битный регистр +1. `0x66` - ставится, если программа иссользует хотя бы 1 16-битный регистр +2. `0x67` - ставится если команда **адресуется** при помощи 32-битных регистров Благо для 8-битных операций другие опкоды и хотя бы на них не надо префиксы запоминать) +## Примеры переводов + + + +## Решение остальных пунктов + +*В целом в этом репозитории лежат файлы, в которых я приложил пока еще не протестированное, но решение для первых нескольких пунктов. Однако в силу того, что память у нас 64-битная, а также я не могу залеть напрямую в видеопамять если не буду собирать модуль ядра. Возможно конечно от нечего делать я сделаю модуль ядра, который позволит выворачивать такие приколы, но это будет точно не на время этого курса.* + +### 01 - простучать команды ассемблеру + +Тут нечего сказать - есть просто колонка с коммандами и просят их использовать. Тут гугл в помощь. + +А вот по поводу полей в команде могу сразу сказать - в 64 битном процессоре все это будет выглядеть немного иначе. Поэтому предлагаю 16-битные регистры заменить в команде на 64 битные и закодировать как для 64 разрядной системы. подробная инструкция как это бы надо бы сделать у меня приведена выше, поэтому тут не буду на этом останаваливаться. + +### 02 - Пересылка массива при помощи loop и lea + +`lea` - это сокращение от "load effective adress". Она использует использует классическую операцию обращения к памяти, но саму память не затрагивает, а просто записывает высчитанный адрес в переменную + +Голая теория никого никогда не радовала, поэтому постараюсь в меру своих сил переконвертировать несколько примеров + +**`mov rax, rbx`** - исходная инструкция + +Для начала в талмудике нам потребуется найти опкод операции. Поэтому ищем табличку для этой операции. В ней нас интересует один из двух покодов: `mov r/m64, r64` и `mov r64, r/m64`. Я возьму второй из этих вариантов, просто чтобы порядок следования регистров совпадал с нашей исходной иструкцией (потом поймете). Для выбранной инструкции приведен следующий opcode: `REX.W + 8B/r` + +Для начала посередине ставим опкод (8b в двоичной): + +[ 1000 1011 ] + +REX байт у нас появляется в любом случае. REX.W - это флаг для REX, который переназначает операнды в размеры 64 бита. Если бы оба наших регистра были бы 32 битные, то этого флага бы не было. Ну а раз REX у нас обязателен, то можно немного определиться, будут ли у нас еще какие-то флаги в этом байте. Еще какие-то флаги могут появиться если вы используете регистры r8-r15, в остальных случаях REX будет выглядеть как [ 0100 1000 ]. У нас эти регистры не используются, поэтому оставим его в таком виде + +Промежуточный результат: [ 0100 1000 ] [ 1000 1011 ] + +Далее ModR/M. Первые 2 бита от него определяют будут ли использовать адреса и смещения. Подробнее смотрите выше. В нашем случае мы пересылаем из регистра в регистр, поэтому нам нужен mod = 11. Далее идет поле рег. Конкретно в случае `mov r64, r/m64` по контексту можно догадаться что reg у нас слева. Тремя битами кодируется номер регистра. У rax номер 000, а у rbx номер 011. Как я уже и сказал, в нашем случае регистр приемника слева, поэтому ModR/M: [ 11 000 011 ] + +Итого: [ 0100 1000 ] [ 1000 1011 ] [ 11 000 011 ] + +*примечание: ответ мог бы получиться немного другой, если бы мы взяли первый попавшийся опкод, но можете использовать его в качестве упражнения (ну а что, составители учебника так могут, а я нет?)* + +**`mov r8, r11`** + +Все действия и рассуждения у нас аналогичны примеру выше. Я хотел лишь пару слов сказать о том, как кодировать регистры r8-r15. Как раз для этих целей нам поможет REX байт. Как я уже писал, REX имеет следующую структуру: 0100 WRXB. Бит R используется для расширения поля reg, а бит B используется для расширения поля r/m. Когда идет обращение к регистру из диапазона r8-r15 в соответствующих дополняющих байтах должна стоять единица. То есть r8 в поле reg будет записываться как REX.R == 1 + 000, а r11 в поле r/m как REX.B == 1 + 011. Так что для данной команды повторится все, кроме REX байта, который в свою очередь примет вид [ 0100 1101 ] + +Итого: [ 0100 1101 ] [ 1000 1011 ] [ 11 000 011 ] + +**`lea rbx, [rbp + r12 * 4 + 33]`** + +Для начала повторяем наш процесс поиска в талмудике опкода. В этот раз у нас разночтений нет, у нас есть только вариант с инструкцией `lea r64, m`. Для нее поле opcode выглядит довольно знакомо: `REX.W 8D /r`. REX байт у нас уже задействован и 100% появится, однако я вижу тут регистр r12, что должно сказать мне, что REX байт не ограничится простым [ 0100 1000 ]. Заполним мы его чуть позже, а пока только опкод. [ 1000 1101 ] + +Далее смотрим ModR/M. в нашем случае мы явно будем использовать адрес из оперативной памяти и число 33 для сдвига, поэтому нам нужен режим mod = 01 (можно и 10, но тогда будет куча бесполезных нулей). поле reg не вызывает вопросов - используется регистр rbx, поэтому в REX.R = 0, а reg = 011, а вот с полем r/m все любопытнее. Число, которое идет с плюсом можно пока мысленно вынести за скобки (но не убирать далеко, оно нам еще пригодится), а вот регистры мы уже не можем проморгать. Как мы помним поле r/m хранит только 3 бита, как же адресовать эту адову хренотень? Оказывается в r/m последовательность 100 зарезервирована под добавление еще одного байта - SIB байта. ModRM = [ 01 011 100 ] + +SIB байт состоит из 2 битов SS, которые представляют собой степень двойки, 2^(ss) я буду называть коэфициентом. В нашем случае хочу умножить на 4, поэтому ss = 10. Далее идет 3 бита на индекс - это регистр, который будет умножен на коэфициент. В нашем случае мы хотим умножить r12 на 4. Index регистр расширяется из REX.X (потому что inde**X**). Поэтому нам нужно записать двоичной системе 12 - 1100. Старший бит отправится в REX.X, а остальное в поле index, то есть REX.X == 1 index == 100. Далее идет 3 бита под регистр базы. Он расширяется из REX.B, в нашем случае хочется использовать регистр rbp, он имеет номер 0101, поэтому используем REX.B == 0, base == 101. SIB = [ 10 100 101 ] + +Уже на этом этапе мы видим, что нужно проставить еще одну единицу в REX.X, в остальных же местах используются обычные регистры, поэтому REX = [ 0100 1010 ]. + +Помните, мы запоминали число 33? Ну вот настало его время. Дело в том, что число, которое надо прибавить к итоговому адресу. В нашем случае надо закодировать число 33, это будет 0b00100001, это мы засунем в displecement байт + +Итого: [ 0100 1010 ] [ 1000 1101 ] [ 01 011 100 ] [ 10 100 101 ] [ 0010 0001 ] + +**`inc WORD PTR [2 * rsi + 31]`** + +*Интересный факт, в качестве index не может использоваться rsp* + +Не буду много повторяться. Instruction `lea 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 ] + +Замечу так же, что поскольку не используется ни REX.W ни один из расширенных регистров, REX байт принимал значение 0100 0000, но в таком случае спецификация Intel позволяет этот байт опускать. А вот что опускать нельзя - это префикс переназначения операнда, потому что используется 16 битный регистр. Ну а число для справке у нас в big endian + +Однако тут есть еще один важный момент Мы видим, что в данном случае есть один интересный момент. Вроде mod == 00, но тут 4 байта dispasement. Дело в том, что если mod == 00 а base == 101, то будет адресация вида index * scale + disp32. Довольно весело. Это я к чему? даже если вы знаете все номера регистры, таблицу смотреть все равно надо ## Решение остальных пунктов From e5c09afc6dfaf1d52eba15010b83d2545a65fdf3 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 21 Sep 2024 23:13:33 +0300 Subject: [PATCH 18/21] =?UTF-8?q?feat:=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D1=8B=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D1=85?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B9=20=D0=BD=D0=B0=20?= =?UTF-8?q?nasm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Обязательно понимание того, что я не проверял эти решения) --- 02-cpu-commnads/task2.asm | 29 ++++++++++++++++++ 02-cpu-commnads/task3.asm | 25 +++++++++++++++ 02-cpu-commnads/task5.asm | 64 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 02-cpu-commnads/task2.asm create mode 100644 02-cpu-commnads/task3.asm create mode 100644 02-cpu-commnads/task5.asm diff --git a/02-cpu-commnads/task2.asm b/02-cpu-commnads/task2.asm new file mode 100644 index 0000000..1270702 --- /dev/null +++ b/02-cpu-commnads/task2.asm @@ -0,0 +1,29 @@ +global _start + +section .data + + source: db 1, 2, 3, 4, 5, 6, 7, 8 + s_size equ $-source + +section .bss + + dest: resb 8 + +section .text + +_start: + + lea rsi, [source] + lea rdi, [dest] + mov rcx, s_size + + .loop: + + mov al, [rsi + rcx] + mov [rdi + rcx], al + + loop .loop + + mov rax, 60 + mov rdi, 0 + syscall diff --git a/02-cpu-commnads/task3.asm b/02-cpu-commnads/task3.asm new file mode 100644 index 0000000..b8ec57e --- /dev/null +++ b/02-cpu-commnads/task3.asm @@ -0,0 +1,25 @@ +global _start + +section .data + source: db 1, 2, 3, 4, 5, 6, 7, 8 + s_size equ $-source + +section .bss + + dest: resb 8 + +section .text + +_start: + + mov rsi, source + mov rdi, dest + mov rcx, s_size + + .loop: + rep movsb + loop .loop + + mov rax, 60 + mov rdi, 0 + syscall diff --git a/02-cpu-commnads/task5.asm b/02-cpu-commnads/task5.asm new file mode 100644 index 0000000..c2050ba --- /dev/null +++ b/02-cpu-commnads/task5.asm @@ -0,0 +1,64 @@ +global _start + +section .text + +%define SRC 0xB8000 +%define DST 0xB9000 +%define ARR_SIZE 10 + +%define PROT_READ 0x1 +%define PROT_WRITE 0x2 +%define MAP_PRIVATE 0x02 +%define MAP_ANONYMOUS 0x20 + +_start: + + ; Из-за особенностей ядра линукса нужно сначала промапать произвольную память + mov rax, 0x9 ; mmap + mov rdi, SRC ; где + mov rsi, ARR_SIZE ; сколько + mov rdx, PROT_READ ; флаги чтения + or rdx, PROT_WRITE ; флаги записи + mov r10, MAP_PRIVATE ; приватная память + or r10, MAP_ANONYMOUS ; не связана с файлом + mov r9, 0 ; офсет должен быть 0 + syscall + + + mov rsi, rax ; ставлю так, так как ядро линукса выделяет ближайшую область памяти, а не точно заказанную - проклятое выравнивание + + ; заполню чем-нибудь массив + mov rcx, ARR_SIZE + mov rbx, 0 + + .fill_src_loop: + + mov [rsi + rbx], bl + inc rbx + + loop .fill_src_loop + + push rsi + + mov rax, 0x9 ; mmap + mov rdi, DST ; где + mov rsi, ARR_SIZE ; сколько + mov rdx, PROT_WRITE ; флаги чтения + ; or rdx, PROT_WRITE ; флаги записи + mov r10, MAP_PRIVATE ; приватная память + or r10, MAP_ANONYMOUS ; не связана с файлом + mov r9, 0 ; офсет должен быть 0 + syscall + + mov rdi, rax + ; заполню чем-нибудь массив + + mov rcx, ARR_SIZE ; сколько байт копируем + + pop rsi + rep movsb + + mov rax, 60 + mov rdi, 0 + syscall + From c3ea0cb506b512ca6a5f3aebf14a450c55f6f1d1 Mon Sep 17 00:00:00 2001 From: Miheev Egor Date: Sun, 22 Sep 2024 00:02:13 +0300 Subject: [PATCH 19/21] =?UTF-8?q?feat:=20=D0=BD=D0=B5=D0=BC=D0=BD=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BE=20=D0=BF=D1=83=D0=BD=D0=BA=D1=82=D0=B0?= =?UTF-8?q?=D1=85=20=D0=BB=D0=B0=D0=B1=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02-cpu-commnads/README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/02-cpu-commnads/README.md b/02-cpu-commnads/README.md index 5abb43d..0ad26ec 100644 --- a/02-cpu-commnads/README.md +++ b/02-cpu-commnads/README.md @@ -133,6 +133,10 @@ SIB байт состоит из 2 битов SS, которые предста Однако тут есть еще один важный момент Мы видим, что в данном случае есть один интересный момент. Вроде mod == 00, но тут 4 байта dispasement. Дело в том, что если mod == 00 а base == 101, то будет адресация вида index * scale + disp32. Довольно весело. Это я к чему? даже если вы знаете все номера регистры, таблицу смотреть все равно надо +**Послесловие** + +Это далеко не исчерпывающий набор примеров, но этого хватит для начала. + ## Решение остальных пунктов *В целом в этом репозитории лежат файлы, в которых я приложил пока еще не протестированное, но решение для первых нескольких пунктов. Однако в силу того, что память у нас 64-битная, а также я не могу залеть напрямую в видеопамять если не буду собирать модуль ядра. Возможно конечно от нечего делать я сделаю модуль ядра, который позволит выворачивать такие приколы, но это будет точно не на время этого курса.* @@ -145,7 +149,17 @@ SIB байт состоит из 2 битов SS, которые предста ### 02 - Пересылка массива при помощи loop и lea -`lea` - это сокращение от "load effective adress". Она использует использует классическую операцию обращения к памяти, но саму память не затрагивает, а просто записывает высчитанный адрес в переменную +`lea` - это сокращение от "load effective adress". Она использует использует классическую операцию обращения к памяти, но саму память не затрагивает, а просто записывает высчитанный адрес в переменную. `loop` в свою очередь прыгает на определенную метку пока в rcx не окажется 0 и при каждом прыжке уменьшает значение в rcx на 1. + +### 03 - Пересылка данных через LODS, MOVS, STOS + +LODS и STOS - парные команды. Первая читает из памяти в rax (или его часть), STOS наоборот - пишет в память содержимое rax (или его часть). `movs` перемещает содержимое из [rsi] в [rdi], после чего увеличивает адрес на размер элемента. Это очень хорошо сочетается с префиксом rep, который заставляет повторяет команду пока в rcx не будет 0, а после каждого повторения уменьшает rcx на 1 + +### 05 - Запись в произвольную память + +В линуксе вся память виртуальная, а если попытаться в лоб попробовать написать что-то в рандомный адрес, ядро выдаст segfault. Чтобы этого не произошло необходимо промапать память. Для этого используется системный вызов mmap, про его особенности написано внутри файла. Здесь хотелось бы пояснить вот какой момент: этот системный вызов использует кучу флагов, которые изначально не особенно нам известны. Так вот. Самый быстрый способ найти их - обратиться к include вашего компилятора. Для mmap все лежит в файле . Эти значения я решил занести в define, чтобы код был чуть читаемее + +У mmap есть и другая особенность - он мапает виртуальную память, а не физическую, поэтому то, что в оригинальной методичке мы на самом деле использовали видеобуфер, для нас не имеет реального значения. Я также использовал анонимный приватный маппинг, чтобы не портить жизнь другим процессам и не грузить ничего из файла, поэтому даже попортить жизнь другим процессам у меня не получится