Здравствуйте, уважаемые! Объясните, пожалуста, начинающему программёру. Я делал функцию для обмена значениями, для разных типов в первый раз написал следующий код: void AsmSwap(void*a,void*b){ asm{ pushad mov eax,[a] mov ebx,[b] mov [b],eax mov [a],ebx popad } } Проверил ее и ничего не вышло. Посмотрел я значит под отладчиком и вот что увидел: в регистры копируется не значения по адресу, а сам адрес и естественно, что снаружи это никак не отображается, т.е. ничего не меняется. Хоть пиши в квадратных скобках, хоть вообще без скобок - одинаково работает. Пришлось менять код, в этом все получилось void AsmSwap(void*a,void*b){ asm{ pushad mov ebx,b mov eax,a push [eax] push [ebx] pop [eax] pop [ebx] popad } } Почему
в первом примере не влияют квадратные скобки (Объясните, пожалуста, как для начинающего, попадробнее, если можно.)? Если ответ - просто адреса можно указывать только через регистры, то будьте добры, объясните почему через регистры, или это просто догма. Делал я в C++ Builder 5, gод виндоус 98. Хотя тоже происходит и в DOS'е в borland 3.1 (я проверял, правда там не работали popad, pushad пришлось без них - в ручную не захотелось сохранять все регистры). Спасибо за вашу помощь. С уважением, Алксандр.
Доброе время суток, Alexander! А зачем вы себе жизнь усложняете? Пишите так: asm{ push a push b pop a pop b } И нет никакой мороки с адресами P.S. Регистры можно сохранить Ответ отправлен: 15.05.2004, 17:42 Отправитель: Sedric Отвечает www
Доброе время суток, Alexander! Это скорее вопрос по ассемблеру. Исходя из правил ассемблера, которые распространяются и на ассемблер встроенный в C++ Builder 5, при модификации адресов (что ты и патаешся изобразить квадратными скобками) необходимо использовать регистр модификатор, тогда, например, операция mov [eax],ebx по адресу eax будет записано значение содержащее в ebx. Если же записать mov [a],ebx это будет эквивалентно mov a,ebx, то есть значение ebx запишется по адресу переменной -a-, которая сама является адресом по которому находится нужное значение. Ответ отправлен: 14.05.2004, 19:35 Отправитель: www Отвечает CrackLab
Добрый день, Alexander! Сейчас постараюсь объяснить. Когды ты вызываешь свою первую подпрограмму например так: byte b = 0x30; char c = 'A'; AsmSwap(&b, &c); то параметры передаются функции AsmSwap через стек. В данном случае наши параметры - адреса, по которым непосредственно находятся наши байты 0x30 и 0x41. Внутри функции инструкция mov eax,[a] кладет в eax не то, что ты ожидаешь. Ты думаешь что в eax кладется байт 0x30 (точнее следует ожидать что в eax окажутся 4 байта - 0x30 и три следующих в памяти), но это обман. Дело в том, что параметр а - указатель, поэтому для непосредственному доступу к данным, на которые указывает указатель тебе надо углубиться дважды: сначала инструкция mov eax, [a] получает в eax адрес, по которому хранится байт 0x30, а затем надо еще положить в регистр байт по адресу, который хранится в eax. Ты же в своем примере,
меняешь просто в стеке адреса двух параметров, но эта часть стека, принадлежит процедуре AsmSwap - дня нее значения как будто действительно меняются, но для внешней программы - ничего не меняется. Тут трудно это все объяснить. Лучше тебе еще разобраться в отладчике. Вот посмотри исправленный вариант программы (для обмена двух однобайтовых данных разного типа): void AsmSwap(void*a,void*b) { asm { pushad mov eax,[a] mov ebx,[b] mov cl, byte ptr [eax] mov dl, byte ptr [ebx] mov byte ptr [ebx], cl mov byte ptr [eax], dl popad } } И в отладчике посмотри что происходит. В данной реализации, непосредственно в памяти данные (а не указатели) меняются местами. В этом случае надо чтобы данные были одного размера. Можно просто поменять адреса, на которые указывают указатели, а данные на самом деле останутся на своих адресах. Это можно
сделать например так: int i = 0x41; /* Объявим и прикрепим к непосредственным данным 2 указателя и еще объявим один промежуточный указатель нужный для обмена */ int *b; b = &i; char *c = "LaLaLa"; void *tmp = c; // Обмениваем адреса, на которые указывают указатели c = (char *)b; b = (int *)tmp; Caption = c; // Теперь Caption = "A" а не "LaLaLa" Ну вот вроде и все... Ответ отправлен: 15.05.2004, 13:12 Отправитель: CrackLab
Форма отправки вопроса
Внимание!
Мы рекомендуем открывать рассылку в программе Internet Explorer 5.0+
или отправлять вопросы с сайта по адресу:
http://rusfaq.ru/cgi-bin/Message.cgi.