Доброго всем! Нашёл недавно один пример 16-битного кода nasm и немного решил поиграть с ним. В нём используется valotile (inline). Мне стало интересно (ответ честно искал, но не нашёл), может кто-то подскажет?! Попробую точно сформулировать: можно ли использовать в качестве номера смещения для стека значение регистра?! Т.е., допустим, существует такая строка: Код (Text): __asm__ __volatile__("mov %dl, +16(%ebp)\n"); Вопрос: возможно ли вместо 16 подставить значение регистра, допустим ecx или любого другого? Т.е., проще говоря, подставить туда переменную? В мануале по inline не нашёл об этом ничего. Спасибо!
Регистры в скобках через запятую '(%ebp,%eax)'. Гугли gcc inline assembly. Можно кстати тупо воспользоваться тем, что гцц может в такие листинги компилить, можешь найти примеры в них.
Спасибо. Сработало, но почему-то без одианарных кавычек: Код (Text): __asm__ __volatile__("mov (%ecx,%ebp), %eax\n"); --- Сообщение объединено, 7 фев 2025 --- Если кому-нибудь интересно что я пытался сделать: что-то вроде головоломки (не буду больше гадательные методы для асма использовать). Вывод значения i C через asm в 16-битном режиме: Интересно, что совершенно случайно обнаружил, что i летит в eax, хотя в общем ничего в этом удивительного нет. И, кстати, режим вроде объявлен 16-битный, а регистры дальше 32-битные. Мне кажется, что трудность асма в принципе ещё в том, что ты вроде знаешь что хочешь получить в конце, но делаешь будто на ощупь, будто не до конца понимая внутренние механизмы процессора (что в общем тоже неудивительно). Т.е. не без спец. образования учебник асма можно даже не брать в руки. Смысла нет. Я так понял во всяком случае. Код (Text): [TABLE][TBODY][TR][TD]//gcc -c -g -Os -ffreestanding -Wall -Werror 111_1.c -o 111_1.o; ld -static -T111.ld -nostdlib --nmagic -o 111_1.elf 111_1.o; objcopy -O binary 111_1.elf 111_1.bin; qemu-system-i386 -m 32 -hda 111_1.bin[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]/*генерирует 16-битный код*/[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]__asm__(".code16\n");[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]__asm__(".section .text\n");[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]/*переход к точке входа в загрузочный код*/[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]__asm__("jmpl $0x0000, $main\n");[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]/* пользовательская функция для вывода серии знаков, завершаемых нулевым символом*/[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]void main() {[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]int i = 12;[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]while(i >= 1 ) {[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] //Но дальше у нас 32-битные регистры[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]//Уменьшаем 12[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %eax, %ecx"); //Дублируем в ecx. Там сейчас число 12[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $20, %edi\n"); //Счётчик цикла[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] //Кладём eax в ecx, чтобы потом вернуть значение i[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("loop:"); //Цикл для отправки цифр в стек[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $10, %ebx"); // 10 в ebx[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %edx, %edx"); // Обнулим edx[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("div %ebx"); // Делим eax на ebx[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %eax, %esi"); //Перенесем на время eax в ecx[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %dl, (%edi,%ebp)\n"); //Запишем остаток в стек по адресу 20[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %esi, %eax"); //Вернем в eax оставшееся от деления[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("cmp $16, %edi"); //Условие выхода[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("sub $4, %edi"); //Вычитаем из счётчика[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("jne loop"); //Возврат в цикл[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $16, %edi\n"); //Кладём 16 в edi - Счётчик[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("loop2:"); //Цикл 2. Вывод[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov (%edi,%ebp), %eax\n"); //Кладём из стека по адресу 16 в eax[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("add $'0', %al"); // Добавим 0, чтобы напечатать символ[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $0x0e, %ah\n"); //Телетайп[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("int $0x10\n"); //Прерывание[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("add $4, %edi"); //Увеличим счётчик[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("cmp $24, %edi"); //Условие выхода[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("jne loop2"); //Возврат в цикл[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]//Возвращаем значение i[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %ecx, %eax");[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD]i--;[/TD][/TR][/TBODY][/TABLE] [TABLE][TBODY][TR][TD] }[/TD][/TR][/TBODY][/TABLE] } [TABLE][TBODY][TR][TD]//Команда сборки. Требуется файл 111.ld[/TD][/TR][/TBODY][/TABLE] Код (Text): [TABLE][TBODY][TR][TD]ENTRY(main);[/TD][/TR][/TBODY] [TBODY][TR][TD]SECTIONS[/TD][/TR][/TBODY] [TBODY][TR][TD]{[/TD][/TR][/TBODY] [TBODY][TR][TD] . = 0x7C00;[/TD][/TR][/TBODY] [TBODY][TR][TD] .text : AT(0x7C00)[/TD][/TR][/TBODY] [TBODY][TR][TD] {[/TD][/TR][/TBODY] [TBODY][TR][TD] *(.text);[/TD][/TR][/TBODY] [TBODY][TR][TD] }[/TD][/TR][/TBODY] [TBODY][TR][TD] .sig : AT(0x7DFE)[/TD][/TR][/TBODY] [TBODY][TR][TD] {[/TD][/TR][/TBODY] [TBODY][TR][TD] SHORT(0xaa55);[/TD][/TR][/TBODY] [TBODY][TR][TD] }[/TD][/TR][/TBODY] [TBODY][TR][TD]} [/TD][/TR][/TBODY][/TABLE] --- Сообщение объединено, 7 фев 2025 --- Извиняюсь, не знаю, что там с форматированием. Код (Text): ENTRY(main); SECTIONS { . = 0x7C00; .text : AT(0x7C00) { *(.text); } .sig : AT(0x7DFE) { SHORT(0xaa55); } } --- Сообщение объединено, 7 фев 2025 --- Сам код: Код (Text): /*генерирует 16-битный код*/ __asm__(".code16\n"); __asm__(".section .text\n"); /*переход к точке входа в загрузочный код*/ __asm__("jmpl $0x0000, $main\n"); /* пользовательская функция для вывода серии знаков, завершаемых нулевым символом*/ void main() { int i = 12; while(i >= 1 ) { //Но дальше у нас 32-битные регистры //Уменьшаем 12 __asm__ __volatile__("mov %eax, %ecx"); //Дублируем в ecx. Там сейчас число 12 __asm__ __volatile__("mov $20, %edi\n"); //Счётчик цикла //Кладём eax в ecx, чтобы потом вернуть значение i __asm__ __volatile__("loop:"); //Цикл для отправки цифр в стек __asm__ __volatile__("mov $10, %ebx"); // 10 в ebx __asm__ __volatile__("xor %edx, %edx"); // Обнулим edx __asm__ __volatile__("div %ebx"); // Делим eax на ebx __asm__ __volatile__("mov %eax, %esi"); //Перенесем на время eax в ecx __asm__ __volatile__("mov %dl, (%edi,%ebp)\n"); //Запишем остаток в стек по адресу 20 __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax __asm__ __volatile__("mov %esi, %eax"); //Вернем в eax оставшееся от деления __asm__ __volatile__("cmp $16, %edi"); //Условие выхода __asm__ __volatile__("sub $4, %edi"); //Вычитаем из счётчика __asm__ __volatile__("jne loop"); //Возврат в цикл __asm__ __volatile__("mov $16, %edi\n"); //Кладём 16 в edi - Счётчик __asm__ __volatile__("loop2:"); //Цикл 2. Вывод __asm__ __volatile__("mov (%edi,%ebp), %eax\n"); //Кладём из стека по адресу 16 в eax __asm__ __volatile__("add $'0', %al"); // Добавим 0, чтобы напечатать символ __asm__ __volatile__("mov $0x0e, %ah\n"); //Телетайп __asm__ __volatile__("int $0x10\n"); //Прерывание __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax __asm__ __volatile__("add $4, %edi"); //Увеличим счётчик __asm__ __volatile__("cmp $24, %edi"); //Условие выхода __asm__ __volatile__("jne loop2"); //Возврат в цикл //Возвращаем значение i __asm__ __volatile__("mov %ecx, %eax"); i--; } } P.S. Отредактировать уже не могу. Первые два кода можно удалить. --- Сообщение объединено, 7 фев 2025 --- --- Сообщение объединено, 7 фев 2025 --- Т.е. * без спец. образования учебник асма можно даже не брать в руки.