Inline (valotile) asm. Значение регистра в качестве номера смещения

Тема в разделе "WASM.BEGINNERS", создана пользователем dcc0, 6 фев 2025.

  1. dcc0

    dcc0 Member

    Публикаций:
    2
    Регистрация:
    22 дек 2022
    Сообщения:
    81
    Доброго всем!
    Нашёл недавно один пример 16-битного кода nasm и немного решил поиграть с ним.
    В нём используется valotile (inline).
    Мне стало интересно (ответ честно искал, но не нашёл), может кто-то подскажет?! Попробую точно сформулировать: можно ли использовать в качестве номера смещения для стека значение регистра?!
    Т.е., допустим, существует такая строка:
    Код (Text):
    1. __asm__ __volatile__("mov %dl, +16(%ebp)\n");
    Вопрос: возможно ли вместо 16 подставить значение регистра, допустим ecx или любого другого?
    Т.е., проще говоря, подставить туда переменную?
    В мануале по inline не нашёл об этом ничего.
    Спасибо!
     
    Последнее редактирование: 6 фев 2025
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.018
    Регистры в скобках через запятую '(%ebp,%eax)'.

    Гугли gcc inline assembly. Можно кстати тупо воспользоваться тем, что гцц может в такие листинги компилить, можешь найти примеры в них.
     
  3. Treant

    Treant Member

    Публикаций:
    0
    Регистрация:
    24 май 2009
    Сообщения:
    261
    вплоть до такого можно Base + (Index * Scale) + Displacement
     
  4. dcc0

    dcc0 Member

    Публикаций:
    2
    Регистрация:
    22 дек 2022
    Сообщения:
    81
    Спасибо. Сработало, но почему-то без одианарных кавычек:
    Код (Text):
    1. __asm__ __volatile__("mov (%ecx,%ebp), %eax\n");
    --- Сообщение объединено, 7 фев 2025 ---
    Если кому-нибудь интересно что я пытался сделать: что-то вроде головоломки (не буду больше гадательные методы для асма использовать).

    Вывод значения i C через asm в 16-битном режиме:
    Интересно, что совершенно случайно обнаружил, что i летит в eax, хотя в общем ничего в этом удивительного нет.

    И, кстати, режим вроде объявлен 16-битный, а регистры дальше 32-битные.
    Мне кажется, что трудность асма в принципе ещё в том, что ты вроде знаешь что хочешь получить в конце, но делаешь будто на ощупь,
    будто не до конца понимая внутренние механизмы процессора (что в общем тоже неудивительно).
    Т.е. не без спец. образования учебник асма можно даже не брать в руки. Смысла нет. Я так понял во всяком случае.

    Код (Text):
    1.  
    2. [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]
    3. [TABLE][TBODY][TR][TD]/*генерирует 16-битный код*/[/TD][/TR][/TBODY][/TABLE]
    4. [TABLE][TBODY][TR][TD]__asm__(".code16\n");[/TD][/TR][/TBODY][/TABLE]
    5. [TABLE][TBODY][TR][TD]__asm__(".section .text\n");[/TD][/TR][/TBODY][/TABLE]
    6. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    7. [TABLE][TBODY][TR][TD]/*переход к точке входа в загрузочный код*/[/TD][/TR][/TBODY][/TABLE]
    8. [TABLE][TBODY][TR][TD]__asm__("jmpl $0x0000, $main\n");[/TD][/TR][/TBODY][/TABLE]
    9. [TABLE][TBODY][TR][TD]/* пользовательская функция для вывода серии знаков, завершаемых нулевым символом*/[/TD][/TR][/TBODY][/TABLE]
    10. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    11. [TABLE][TBODY][TR][TD]void main() {[/TD][/TR][/TBODY][/TABLE]
    12. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    13. [TABLE][TBODY][TR][TD]int i = 12;[/TD][/TR][/TBODY][/TABLE]
    14. [TABLE][TBODY][TR][TD]while(i >= 1 ) {[/TD][/TR][/TBODY][/TABLE]
    15. [TABLE][TBODY][TR][TD] //Но дальше у нас 32-битные регистры[/TD][/TR][/TBODY][/TABLE]
    16. [TABLE][TBODY][TR][TD]//Уменьшаем 12[/TD][/TR][/TBODY][/TABLE]
    17. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    18. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %eax, %ecx"); //Дублируем в ecx. Там сейчас число 12[/TD][/TR][/TBODY][/TABLE]
    19. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    20. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $20, %edi\n"); //Счётчик цикла[/TD][/TR][/TBODY][/TABLE]
    21. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    22. [TABLE][TBODY][TR][TD] //Кладём eax в ecx, чтобы потом вернуть значение i[/TD][/TR][/TBODY][/TABLE]
    23. [TABLE][TBODY][TR][TD] __asm__ __volatile__("loop:"); //Цикл для отправки цифр в стек[/TD][/TR][/TBODY][/TABLE]
    24. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    25. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $10, %ebx"); // 10 в ebx[/TD][/TR][/TBODY][/TABLE]
    26. [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %edx, %edx"); // Обнулим edx[/TD][/TR][/TBODY][/TABLE]
    27. [TABLE][TBODY][TR][TD] __asm__ __volatile__("div %ebx"); // Делим eax на ebx[/TD][/TR][/TBODY][/TABLE]
    28. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %eax, %esi"); //Перенесем на время eax в ecx[/TD][/TR][/TBODY][/TABLE]
    29. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %dl, (%edi,%ebp)\n"); //Запишем остаток в стек по адресу 20[/TD][/TR][/TBODY][/TABLE]
    30. [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax[/TD][/TR][/TBODY][/TABLE]
    31. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %esi, %eax"); //Вернем в eax оставшееся от деления[/TD][/TR][/TBODY][/TABLE]
    32. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    33. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    34. [TABLE][TBODY][TR][TD] __asm__ __volatile__("cmp $16, %edi"); //Условие выхода[/TD][/TR][/TBODY][/TABLE]
    35. [TABLE][TBODY][TR][TD] __asm__ __volatile__("sub $4, %edi"); //Вычитаем из счётчика[/TD][/TR][/TBODY][/TABLE]
    36. [TABLE][TBODY][TR][TD] __asm__ __volatile__("jne loop"); //Возврат в цикл[/TD][/TR][/TBODY][/TABLE]
    37. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    38. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    39. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $16, %edi\n"); //Кладём 16 в edi - Счётчик[/TD][/TR][/TBODY][/TABLE]
    40. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    41. [TABLE][TBODY][TR][TD] __asm__ __volatile__("loop2:"); //Цикл 2. Вывод[/TD][/TR][/TBODY][/TABLE]
    42. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    43. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov (%edi,%ebp), %eax\n"); //Кладём из стека по адресу 16 в eax[/TD][/TR][/TBODY][/TABLE]
    44. [TABLE][TBODY][TR][TD] __asm__ __volatile__("add $'0', %al"); // Добавим 0, чтобы напечатать символ[/TD][/TR][/TBODY][/TABLE]
    45. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov $0x0e, %ah\n"); //Телетайп[/TD][/TR][/TBODY][/TABLE]
    46. [TABLE][TBODY][TR][TD] __asm__ __volatile__("int $0x10\n"); //Прерывание[/TD][/TR][/TBODY][/TABLE]
    47. [TABLE][TBODY][TR][TD] __asm__ __volatile__("xor %eax, %eax"); //Обнулим eax[/TD][/TR][/TBODY][/TABLE]
    48. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    49. [TABLE][TBODY][TR][TD] __asm__ __volatile__("add $4, %edi"); //Увеличим счётчик[/TD][/TR][/TBODY][/TABLE]
    50. [TABLE][TBODY][TR][TD] __asm__ __volatile__("cmp $24, %edi"); //Условие выхода[/TD][/TR][/TBODY][/TABLE]
    51. [TABLE][TBODY][TR][TD] __asm__ __volatile__("jne loop2"); //Возврат в цикл[/TD][/TR][/TBODY][/TABLE]
    52. [TABLE][TBODY][TR][TD] [/TD][/TR][/TBODY][/TABLE]
    53. [TABLE][TBODY][TR][TD]//Возвращаем значение i[/TD][/TR][/TBODY][/TABLE]
    54. [TABLE][TBODY][TR][TD] __asm__ __volatile__("mov %ecx, %eax");[/TD][/TR][/TBODY][/TABLE]
    55. [TABLE][TBODY][TR][TD]i--;[/TD][/TR][/TBODY][/TABLE]
    56. [TABLE][TBODY][TR][TD] }[/TD][/TR][/TBODY][/TABLE]
    57. }
    58. [TABLE][TBODY][TR][TD]//Команда сборки. Требуется файл 111.ld[/TD][/TR][/TBODY][/TABLE]
    59.  
    60.  
    Код (Text):
    1.  
    2. [TABLE][TBODY][TR][TD]ENTRY(main);[/TD][/TR][/TBODY]
    3. [TBODY][TR][TD]SECTIONS[/TD][/TR][/TBODY]
    4. [TBODY][TR][TD]{[/TD][/TR][/TBODY]
    5. [TBODY][TR][TD] . = 0x7C00;[/TD][/TR][/TBODY]
    6. [TBODY][TR][TD] .text : AT(0x7C00)[/TD][/TR][/TBODY]
    7. [TBODY][TR][TD] {[/TD][/TR][/TBODY]
    8. [TBODY][TR][TD] *(.text);[/TD][/TR][/TBODY]
    9. [TBODY][TR][TD] }[/TD][/TR][/TBODY]
    10. [TBODY][TR][TD] .sig : AT(0x7DFE)[/TD][/TR][/TBODY]
    11. [TBODY][TR][TD] {[/TD][/TR][/TBODY]
    12. [TBODY][TR][TD] SHORT(0xaa55);[/TD][/TR][/TBODY]
    13. [TBODY][TR][TD] }[/TD][/TR][/TBODY]
    14. [TBODY][TR][TD]} [/TD][/TR][/TBODY][/TABLE]
    15.  
    16.  
    --- Сообщение объединено, 7 фев 2025 ---
    Извиняюсь, не знаю, что там с форматированием.
    Код (Text):
    1.  
    2. ENTRY(main);
    3. SECTIONS
    4. {
    5.   . = 0x7C00;
    6.   .text : AT(0x7C00)
    7.   {
    8.   *(.text);
    9.   }
    10.   .sig : AT(0x7DFE)
    11.   {
    12.   SHORT(0xaa55);
    13.   }
    14. }
    15.  
    16.  
    --- Сообщение объединено, 7 фев 2025 ---
    Сам код:
    Код (Text):
    1.  
    2. /*генерирует  16-битный код*/
    3. __asm__(".code16\n");
    4. __asm__(".section .text\n");
    5.  
    6. /*переход к точке входа в загрузочный код*/
    7. __asm__("jmpl $0x0000, $main\n");
    8. /* пользовательская функция для вывода серии знаков, завершаемых нулевым символом*/
    9.  
    10. void main() {
    11.  
    12. int i = 12;
    13. while(i >= 1  ) {
    14.    //Но дальше у нас 32-битные регистры
    15. //Уменьшаем 12
    16.  
    17.     __asm__ __volatile__("mov %eax, %ecx"); //Дублируем в ecx. Там сейчас число 12
    18.  
    19.     __asm__ __volatile__("mov $20, %edi\n"); //Счётчик цикла
    20.  
    21.    //Кладём eax в ecx, чтобы потом вернуть значение i
    22.    __asm__ __volatile__("loop:"); //Цикл для отправки цифр в стек
    23.  
    24.     __asm__ __volatile__("mov $10, %ebx");  // 10 в ebx
    25.     __asm__ __volatile__("xor %edx, %edx");  // Обнулим edx
    26.     __asm__ __volatile__("div %ebx");  // Делим eax на ebx
    27.     __asm__ __volatile__("mov %eax, %esi");  //Перенесем на время eax в ecx
    28.     __asm__ __volatile__("mov %dl, (%edi,%ebp)\n");  //Запишем остаток в стек по адресу 20
    29.     __asm__ __volatile__("xor %eax, %eax");  //Обнулим eax
    30.     __asm__ __volatile__("mov %esi, %eax");  //Вернем в eax оставшееся от деления
    31.  
    32.  
    33.   __asm__ __volatile__("cmp $16, %edi"); //Условие выхода
    34.   __asm__ __volatile__("sub $4, %edi"); //Вычитаем из счётчика
    35.    __asm__ __volatile__("jne loop");  //Возврат в цикл
    36.  
    37.  
    38.   __asm__ __volatile__("mov $16, %edi\n"); //Кладём 16 в edi - Счётчик
    39.  
    40.    __asm__ __volatile__("loop2:"); //Цикл 2. Вывод
    41.  
    42.     __asm__ __volatile__("mov (%edi,%ebp), %eax\n"); //Кладём из стека по адресу 16 в eax
    43.   __asm__ __volatile__("add $'0', %al");  // Добавим 0, чтобы напечатать символ
    44.   __asm__ __volatile__("mov $0x0e, %ah\n"); //Телетайп
    45.   __asm__ __volatile__("int  $0x10\n");  //Прерывание
    46.   __asm__ __volatile__("xor %eax, %eax");  //Обнулим eax
    47.  
    48.   __asm__ __volatile__("add $4, %edi"); //Увеличим счётчик
    49.   __asm__ __volatile__("cmp $24, %edi"); //Условие выхода
    50.       __asm__ __volatile__("jne loop2");  //Возврат в цикл
    51.  
    52. //Возвращаем значение i
    53.   __asm__ __volatile__("mov  %ecx, %eax");
    54. i--;
    55.    }
    56. }
    57.  
    58.  
    P.S.
    Отредактировать уже не могу. Первые два кода можно удалить.
    --- Сообщение объединено, 7 фев 2025 ---
    [​IMG]
    --- Сообщение объединено, 7 фев 2025 ---
    Т.е. * без спец. образования учебник асма можно даже не брать в руки.