unix-asm-mini-A1
FAQ по асму в никсах от мыщъх'а\\ (фрагмент)
Q3:что такое Intel и AT&T нотация?
AT&T синтаксис разрабатывался компанией AT&T в те далекие времена, когда никакого Intel'а вообще не существовало, процессоры менялись как перчатки и знание нескольких ассемблеров было вполне нормальным явлением. По сравнению с синтаксисом Intel, AT&T-синтаксис намного более избыточен, но это сделано умышленно с целью сокращения ошибок (хинт: на одном процессоре команда MOV может перемещать 32-бита, на другом 16, а на третьем вообще 64).
Отличия синтаксиса AT&T от Intel следующие:
- имена регистров предваряются префиксом: «%«:
- Intel:eax,ebx,dl;
- AT&T:%eax,%ebx,%dl;
- обратный порядок операндов: вначале источник, затем приёмник:
- Intel:moveax, ebx;
- AT&T:movl%ebx, %eax;
- размер операнда задается суффиксом, замыкающим инструкцию, всего есть три типа суффиксов: «b» — байт (8-бит), «w« – слово (16-бит) и «l« – двойное слово (32-бита):
- Intel:movah, al;
- AT&T:movb%al,%ah;
- Intel: movbx, ax;
- AT&T:movw%ax,%bx;
- Intel:moveax,ebx;
- AT&T:movl%ebx,%eax;
- числовые константы записываются в Си-соглашении:
- Intel:69h;
- AT&T:0x69;
- для получения смещения метки используется префикс «$», отсутствие которого приводит к чтению содержимого ячейки:
- Intel:moveax, offset label;
- AT&T:movl$label, %eax;
- Intel:moveax, [label];
- AT&T:movllabel, %eax;
- в тех случаях, когда метка является адресом перехода, префикс «$» опускается:
- Intel:jmplabel;
- AT&T:jmplabel;
- Intel:jmp–;
- AT&Tjmp0x69;
- для косвенного перехода по адресу используется префикс «*»:
- Intel:jmpdword ptr ds:[69h];
- AT&T:jmp*0x69;
- Intel:jmpdword ptr ds:[label];
- AT&T:jmp*label;
- Intel:jmpeax;
- AT&T:jmp*%eax;
- Intel:jmpdword ptr ds: [eax];
- AT&T:jmp*(%eax);
- использование префикса «$» перед константой используется для получения ее значения. знак (если он есть) ставится после префикса. константа без указателя трактуется как указатель:
- Intel:moveax, 69h;
- AT&Tmovl$0x69, %eax;
- Intel:moveax, -69h;
- AT&Tmovl$-0x69, %eax;
- Intel:moveax, [69h];
- AT&Tmovl0x69, %eax
- для реализации косвенной адресации базовый регистр заключается в круглые скобки, перед которыми может присутствовать индекс, записанный в виде числовой константы или метки _без_ префикса «$»:
- Intel:moveax, [ebx];
- AT&T:movl(%ebx), %eax;
- Intel:moveax, [ebx+69h];
- AT&T:movl0x69(%ebx), %eax;
- Intel:moveax, [ebx+label];
- AT&T:movllabel(%ebx), %eax;
- если регистров несколько, то они разделаются через запятую:
- Intel:moveax, [ebx+ecx];
- AT&T:movl(%ebx, %ecx), %eax;
- для задания коэффициента масштабирования (scale) перед первым регистром ставится ведущая запятая (при использовании базово индексной адресации запятая опускается), а сам коэффициент отделяется другой запятой, без префикса «$»:
- Intel:moveax, [ebx*8];
- AT&Tmovl(,%ebx, 8), %eax
- Intel:moveax, [ebx*8+label];
- AT&Tmovllabel(,%ebx, 8), %eax
- Intel:moveax, [ecx+ebx*8+label];
- AT&T:movllabel(%ecx, %ebx, 8);
- Intel:moveax, [ebx+ecx*8+label];
- AT&T:movllabel(%ebx, %ecx, 8);
- сегментная адресация с использованием сегментных регистров отличается от Intel'а использованием круглых скобок вместо квадратных:
- Intel:moveax, es:[ebx];
- AT&T:mov%es:(%bx), %eax;
- в командах переходов и вызовов функций непосредственные сегмент и смещение разделяется не двоеточием, а запятой:
- Intel:jmp far 10h:100000h (псевдоконструкция!)
- jmp$0x10, $0x100000;