Biblioteka assemblera x64 C/C++

0

Cześć,

potrzebuję biblioteki, która ze stringa potrafi wygenerować bytecode assemblera x64. Problem podobny do: http://stackoverflow.com/questions/17001094/c-library-x86-x64-assembler
Jednak mnie nie stać na użycie LLVM (a w zasadzie to libclang, które waży 50MB), i przydałby mi się jakiś tiny assembler x64.

Podkreślam, że chodzi o bibliotekę. Wywołanie jakiegoś kompilatora/assemblera z poziomu systemu odpada, dołączanie dllki >10 MB też odpada, inline assembly nawet nie mam, dołączanie plików .asm do projektu odpada.
Moje poszukiwania nie skończyły się znalezieniem czegokolwiek co by się nadawało, ale być może wy macie jakieś pomysły.

Dodam, że potrzebne mi to tylko do trywialnych instrukcji, typu:

mov rcx, rdx
mov rcx, [rsp+0x100]
movq r9, xmm2
1

Biblioteka do programatycznego generowania assemblera:
https://github.com/asmjit/asmjit (~250k)
Jak koniecznie chcesz ze stringa to jest biblioteka, ktora bazuje na asmjit:
https://github.com/asmjit/asmtk

0

Możesz printowalnymi instrukcjami zapisywać, albo pisać tylko printowalnymi i odczytywać. link

1

Poszukaj kodu rasm2:

$ rasm2 -a x86 -b 64 'mov rax, 23; mov rax, [rax]'
48c7c017000000488b00
2
mwl4 napisał(a):

Dodam, że potrzebne mi to tylko do trywialnych instrukcji, typu:

Czy dużo będzie różnych tych „trywialnych” instrukcji?

Bo może wystarczy doczytać/obadać jak wyglądają te instrukcje i generować samemu.

Przykładowo, podane wyżej instrukcje

mov rcx, rdx
mov rcx, [rsp+0x100]
movq r9, xmm2

to (skompilowane NASMem):

48 89 D1 48 8B 8C 24 00 01 00 00 66 49 0F 7E D1

co można podzielić na (robię to z głowy):

48 89 D1
48 8B 8C 24 00 01 00 00
66 49 0F 7E D1

Offset +0x100 z drugiej instrukcji widać na czterech jej ostatnich bajtach (little endian).
Początkowe bajty 48 to prefiksy REX (oznaczające że instrukcja korzysta z nowych rejestrów x64).
Następne 89 i 8B to różne rodzaje mov.
W ostatniej instrukcji prefix 66 oznacza w tym przypadku instrukcję SSE (w przeciwieństwie do MMX), prefix REX 49 że będzie użyty jeden z nowych rejestrów (r9), następnie 0F 7E to zapewne sam movq (instrukcje MMX i SSE zwykle zaczynają się na 0F).
Dodatkowe bajty (D1 w pierwszej i trzeciej, 8C 24 w drugiej) zawierają resztę informacji, czyli użyte rejestry. Tych na pamięć nie znam.

Tyle z głowy bez patrzenia w dokumentację.

1

Ja myślę podobnie jak @Azarien.
Spisz potrzebne instrukcje i obadaj bajtowo jak one wyglądają.
Miałem niedawno podobny problem, bo potrzebowałem generować podstawowe instrukcje, to napisałem sobie generator prosty, nawet dokumentacja od intela nie jest potrzebna w 100% bo starczy jakiś doc jak sandpile.org i generowanie kodu nasmem (btw, nasm nie obsługuje adresowania z RIP :/) i sprawdzanie jak sie zmienia pod disassemblerem.
Jednakże potem jak już potrzebowałem złożonych instrukcji, to generowałem sobie NASMem, libka nie była potrzebna mi.
Generalnie generacja podstawowych instrukcji jest dosyć łatwa, także implementacja nie będzie długa. Schody mogą być przy bardziej złożonych.

4
Proxima napisał(a):

nasm nie obsługuje adresowania z RIP :/

Nieprawda.

mov eax, [rel dword x]

Przeciwieństwiem rel jest abs. Domyślnie jest abs. Można zmieniać dyrektywą default:

mov eax, [dword x] ; abs
mov eax, [rel dword x] ; rel

[default rel]

mov eax, [dword x] ; rel
mov eax, [abs dword x] ; abs

1 użytkowników online, w tym zalogowanych: 0, gości: 1