bilka00
bilka00
Anonymous
Не очень понятно зачем массовый набег необходим
Anonymous
Впрочем, это оффтопик. Замолкаю
Anonymous
всем привет мне надо что то на бота пройти проверку или нет?
Anonymous
Чего ты от ассемблера хочешь? Как ты дошёл до жизни такой?
я наверно покажусь дураком, но на линуксах меня начал раздражать тот факт, что не всегда драйвера есть в дитсрибутивах линукс ( в их репозиториях ? хз), и я решил что нужно научится писать самому драйвера ( а у меня случай с wifi адаптером). А т.к чтобы хорошо понимать С, я решил начать с ассамблера, как то так
електр🟢нік ✙🟠рчбеч ඞ
електр🟢нік ✙🟠рчбеч ඞ
я так свой неработающий синкпад поднял
електр🟢нік ✙🟠рчбеч ඞ
redcat
Буйный
Broadcom небось
Anonymous
Anonymous
Anonymous
Anonymous
на линуксы
Anonymous
а куда мне писать по вопросам asm сюда или в флудилку?
Туда по вопросам новичка и не совсем ассемблерные вопросы.
Anonymous
Vlad
всем привет
Vlad
почему после захода в zf_1:
Vlad
код заходит в zf_0
Ilya
Потому что ассемблер выполняется последовательно, а в конце zf_1 ты никуда не прыгнул
Vlad
то есть здесь будет точно так же
Vlad
после ZF_1:
Vlad
он зайдет так же в zf_0:
Eugene
Кончено, точно так же.
У тебя что после mov ah,1 идёт?
mov ah,0 — это и исполнится, а ты чего ожидал? Где переход?
Метка не обозначает начало или конец какого-то блока. Это просто обозначение места, куда должен быть прыжок или где находятся какие-то данные, не более.
Eugene
А когда я вижу связки вроде вот этих jz + jmp, меня аж передёргивает. Зачем тут jmp, когда можно jz заменить на jnz?
Eugene
Кончено, точно так же.
У тебя что после mov ah,1 идёт?
mov ah,0 — это и исполнится, а ты чего ожидал? Где переход?
Метка не обозначает начало или конец какого-то блока. Это просто обозначение места, куда должен быть прыжок или где находятся какие-то данные, не более.
Никаких автоматических переходов, пропусков кода и пр. нет в ассемблере.
Даже если ты вставишь процедуру посреди кода, она выполнится (через неё не будет прыжка, т.к. proc/endp — это тоже просто метки и директивы компилятора, процессору на них плевать).
И даже если ты напишешь
mov ah,9
mov dx,offset abc
abc:
db 'hello'
int 21h
то после mov выполнится не int, а db 'hello' (а что это — см. в дизассемблере).
И т.д.
Vlad
Спасибо большое
Vlad
Уяснил
Ivan
Парни, я пишу обёртку _start для main под Linux x86-64, чтобы избавиться от stdlib (флаг -nostdlib для gcc).
То есть просто нужно передать argc, argv во внешний символ main, но чё-та с argv в main, который уже на C реализован, какие-то проблемы.
argc получается такой, как ожидалось.
.globl _start
_start:
/* clear the frame pointer */
xor %ebp, %ebp
/* extract arguments and set up for main */
pop %rdi
pop %rsi
/* The stack pointer %rsp must be aligned to a 16-byte boundary before making a call */
and $0xfffffffffffffff0, %rsp
call main
/* get return value for exit call */
mov %rax, %rdi
/* call exit on kernel */
mov $60, %rax
syscall
Что я делаю не так? Плиз хелп. Асмом под i386 только в студенческие годы занимался, с x86-64 дела не имел на таком уровне.
Dmitrij
попробуй:
pushq %rbp
movq %rsp, %rbp
вместо xor %ebp, %ebp
Dmitrij
и символ main не обязателен если libc не линкуется...
Ivan
main чисто для консистентности, чтобы выглядело как нормальная программа на C.
Если заменяю, xor %ebp, %ebp на pushq %rbp и movq %rsp, %rbp, то уже и argc становится невалидным в main :(
Dmitrij
может main написана под 32бита и аргументы берёт из стека а не из регистров ?
Ivan
Не, как раз проверено опытным путём, что main берёт аргументы из RDI и RSI — mov'ал туда магические числа и делал return argc и return argv для exitcode
Dmitrij
не уверен, но можно попробовать :
movabsq $main, %r8
callq *%r8
Eugene
Eugene
Но вообще, внешний rbp по логике влиять не должен никак.
Eugene
Т.е. первый pop — кол-во аргументов.
Следующий pop — указатель на нулевой аргумент (имя файла).
Следующий pop — указатель на первый аргумент.
Следующий pop — указатель на второй аргумент.
Т.е. получается так:
# rbp вообще не трогаем — это забота вызываемой функции
pop %rdi
mov %rsp, %rsi
and $-16, %rsp
call main
Dmitrij
Eugene
Dmitrij
та неее, на стек аргументы кладутся только для 32бит (по крайней мере первые 6 в linux)
кстати что за платформа ? линукс или виндоус ?
Ivan
Eugene
Dmitrij
On x86-64 UNIX systems(http://www.x86-64.org/documentation/abi-0.99.3.pdf), including Linux and default NetRun, the first six parameters go into rdi, rsi, rdx, rcx, r8, and r9.
Eugene
On x86-64 UNIX systems(http://www.x86-64.org/documentation/abi-0.99.3.pdf), including Linux and default NetRun, the first six parameters go into rdi, rsi, rdx, rcx, r8, and r9.
Не открывается у меня что-то этот файл, можешь прикрепить?
И там точно про параметры именно при запуске?
Вообще, при syscall по ABI x64 параметры передаются немного в другом подярке: rdi, rsi, rdx, r10, r8, r9.
Но там rcx заменён на r10, потому что инструкция syscall сохраняет в rcx значение rip.
Dmitrij
https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
27 страница
Dmitrij
ну main то не является системным вызовом ? или я что-то упустил из виду ?
Eugene
Eugene
Вот тут пишут, что в стеке всё.
https://stackoverflow.com/questions/3683144/linux-64-command-line-parameters-in-assembly
Eugene
Most important (for more information see examples below): in x86-64 the command line arguments are passed via stack:
(%rsp) -> number of arguments
8(%rsp) -> address of the name of the executable
16(%rsp) -> address of the first command line argument (if exists)
... so on ...
It is different from the function parameter passing in x86-64, which uses %rdi, %rsi and so on.
Dmitrij
#book #abi #x86_64 x86_64 abi
Dmitrij
#book #abi #x86_64 x86_64 cheatsheet
Eugene
Ivan
Dmitrij
#book #manual #x86_64 #abi #win64
Соглашения о вызовах в x86_64 Windows OS:
Первые четыре параметра помещаются в регистрах: rcx, rdx, r8, и r9 соответственно.
Остальные параметры идут через стек, справа налево.
Перед вызовом функции, стек должен быть уменьшен на 32байта + 8байт для каждого параметра которые идут через стек (+16 для long double ?).
Если передавать числа с плавающей точкой, то первые четыре помещаются в регистры XMM0-XMM3. Пример:
void my_func(int a, double b, int c, float d);
Arguments a in RCX, b in XMM1, c in R8, and d in XMM3.
PS: эту инфу прикрепил под тэгом win64
Eugene
Ещё важно, что стек должен быть выровнен по границе 16 байт перед вызовом функции (т.е. перед call).
Таким образом, внутри функции структура стека будет такова:
адрес возврата (1 qword = 8 байт)
буфер для сохранения параметров (4 qword = 32 байта)
параметр 5
параметр 6
параметр 7
...
выравнивание (при необходимости 1 qword = 8 байт)
Сразу после вызова функции младшая тетрада esp (esp and 0x0F) = 8.
Dmitrij
Eugene
Да, но если у тебя будет передаваться нечётное кол-во параметров >= 5, то нужно будет ещё на 8 байт скидывать.
Eugene
Потому что ты сделаешь 1, 3, 5... push'ей и будет опять 8 на конце.
Eugene
Причём, т.к. у тебя на входе должна быть 8-ка, то после того как ты сделаешь and esp, 8 байт откусишь, а потом для выравнивания ещё 8 байт откусишь, т.о. лишние 16 байт стека у тебя будут выброшены за зря.
Dmitrij
Причём, т.к. у тебя на входе должна быть 8-ка, то после того как ты сделаешь and esp, 8 байт откусишь, а потом для выравнивания ещё 8 байт откусишь, т.о. лишние 16 байт стека у тебя будут выброшены за зря.
да, ALIGN_STACK у меня вызывется после входа в main/_start (после пролога).
а в invoke что-то такое:
.if __address_size__ == 8
COUNT_ARGS \s1, \s2, \s3, \s4, \s5, \s6
.if aligning != 0
.set __aligned_sp__, __count_number_args__*__address_size__
CALCULATE_ALIGNMENT __aligned_sp__, __aligning_sp__
.endif
.else
COUNT_ARGS \rdi, \rsi, \rdx, \rcx, \r8, \r9, \s1, \s2, \s3, \s4, \s5, \s6
.set __aligned_sp__, __count_number_args__*__address_size__
.set __index_number_args__, 0
.endif
Eugene
Хотя, если сделать пролог
push %rbp
mov %rsp,%rbp
то после and ничего не должно измениться (собственно, можно его и не делать даже).
Eugene
Я не понял, мы про Винду говорим или про Линукс?
Dmitrij
в линухе требование тоже выравнивать по границе 16байт...
Eugene
Просто ты скинул сначала про винду, а последний пример — про линуск (судя по списку регистров).
Кол-во параметров в регистрах разное (4 и 6).