2010-11-06 2 views
1

Я уже задал аналогичный вопрос здесь, но у меня все еще есть некоторые ошибки, поэтому, надеюсь, вы могли бы сказать мне, что я делаю неправильно. Просто знаю, что я знаю ассемблера, и я сделал несколько проектов на ассемблере 8051, и даже это не то же самое, близок к x86 asm.Некоторые вопросы встроенного ассемблера

Существует блок кода, который я попробовал в VC++ 2010 Express (я пытаюсь получить информацию из инструкции CPUID): `

int main() 
{ 
char a[17]; //containing array for the CPUID string 
a[16] = '\0'; //null termination for the std::cout 
void *b=&a[0]; 
int c=0; //predefined value which need to be loaded into eax before cpuid 

_asm 
{ 
    mov eax,c; 
    cpuid; 
    mov [b],eax; 
    mov [b+4],ebx; 
    mov [b+8],ecx; 
    mov [b+12],edx; 
} 
std::cout<<a; 
}` 

Итак, чтобы быстро подвести итог, я попытался создать пустой указатель на первый элемент массива, а не используя косвенную адресацию, просто перемещают значения из регистров. Но этот подход дает мне «стек вокруг переменной b является поврежденной ошибкой во время выполнения», но я не знаю, почему.

Пожалуйста, помогите. Благодарю. И это только для учебных целей, я знаю, что есть функции для CPUID ....

EDIT: Кроме того, как вы можете использовать прямую адресацию в встроенном ассемблере x86 VC++ 2010? Я имею в виду, что общий синтаксис для непосредственной загрузки номера в 8051 равен mov src,#number, но в VC++ asm его mov dest,number без знака #. Итак, как сообщить компилятору, что вы хотите получить адрес ячейки памяти x напрямую?

+1

Вам вообще не нужно c. Просто используйте «xor eax, eax», чтобы установить eax = 0. – TonyK

ответ

6

Причина, по которой ваш стек поврежден, заключается в том, что вы сохраняете значение eax в b. Затем сохраняя значение ebx в ячейке памяти b+4 и т. Д. Синтаксис inline ассемблера [b+4] эквивалентен выражению C++ &(b+4), если b являются указателями байтов.

Вы можете видеть это, если вы смотрите b и одноэтапный. Как только вы выполните mov [b],eax, значение b изменится.

Одним из способов решения этой проблемы заключается в загрузке значение b в индексный регистр и использование индексной адресации:

mov edi,[b] 
mov [edi],eax 
mov [edi+4],ebx 
mov [edi+8],ecx 
mov [edi+12],edx 

Вам не нужно b вообще держать указатель на a. Вы можете загрузить индексный регистр непосредственно с lea (нагрузка эффективный адрес) инструкции:

lea edi,a 
mov [edi],eax 
... etc ... 

Если вы возился с встроенным ассемблером, это хорошая идея, чтобы открыть окно Регистры в отладчик и посмотреть, как все меняется когда вы единый шаг.

Вы также можете напрямую обратиться к памяти:

mov dword ptr a,eax 
mov dword ptr a+4,ebx 
... etc ... 

Однако прямой адресации, как, что требуется больше кодовых байтов, чем индексной адресации в предыдущем примере.

Я думаю, что приведенное выше, с инструкцией lea (Load Effective Address) и прямой адресацией, которую я показал, отвечает на ваш последний вопрос.

0

Совет, чтобы открыть окно Регистры в отладчике, посмотреть, как все изменится, не будет работать в VC++ 2010 Express.

Вы можете быть так же удивлены, как и я, чтобы узнать, что VC++ 2010 Express НЕ ПРОПУСТИТ окно регистров. Это особенно удивительно, так как работа по разборке работает.

Единственное обходное решение, которое я знаю, - открыть окно просмотра и ввести имена регистров в поле «Имя». Тип в EAX EBX ECX EDX ESI EDI EIP ESP EBP EFL и CS DS ES SS FS GS, если вы хотите

ST1 ST2 ST3 ST4 ST5 ST6 ST7 также работает в окне часов.

Возможно, вы также захотите установить значение в шестнадцатеричный, щелкнув правой кнопкой мыши в окне «Часы» и проверив шестнадцатеричный дисплей.