[英]Why does this 16-bit DOS example from a book crash when I call it from C (compiled with visual studio?)
我的操作系統是Windows 7 64位。
這是我的代碼
first.c:
#include <stdio.h>
extern long second(int, int);
void main()
{
int val1, val2;
long result;
scanf("%d %d", &val1, &val2);
result = second(val1, val2);
printf("%ld", result);
}
second.asm:
.model small
.code
public _second
_second proc near
push bp
mov bp,sp
mov ax,[bp+4]
mov bx,[bp+6]
add ax,bx
pop bp
ret
_second endp
end
編譯正常,但是“ mov ax,[bp + 4] ”這一行出現錯誤“ 0xC0000005:訪問沖突讀取位置0x00000004”。
怎么了?
您正在以16位模式組裝代碼,並將其鏈接到以32位模式執行的32位程序。 構成second
功能的機器代碼最終得到的解釋與預期不同。 此實際執行的代碼:
_second:
00407800: 55 push ebp
00407801: 8B EC mov ebp,esp
00407803: 8B 46 04 mov eax,dword ptr [esi+4]
00407806: 8B 5E 06 mov ebx,dword ptr [esi+6]
00407809: 03 C3 add eax,ebx
0040780B: 5D pop ebp
0040780C: C3 ret
該代碼不是使用16位寄存器,而是使用32位寄存器。 在尋址堆棧上的參數時,它使用ESI作為基數,而不是使用BP寄存器作為基數。 由於ESI沒有在函數中初始化為任何東西,因此它保留調用前碰巧具有的任何隨機值(例如0)。 凡是不是有效的可讀地址的地方,因此訪問它會導致崩潰。
您的問題是您已經使用了要與16位編譯器一起用於16位操作系統(例如MS-DOS)的匯編代碼,並使其與32位編譯器一起用於Windows。 您不能盲目剪切和粘貼這樣的代碼示例。 這是您的匯編代碼的32位版本:
.MODEL FLAT
.CODE
PUBLIC _second
_second PROC
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov edx, [ebp+12]
add eax, edx
pop ebp
ret
_second ENDP
END
.MODEL FLAT
指令告訴匯編器您正在生成32位代碼。 我將代碼更改為使用32位寄存器,並調整了幀指針(EBP)的相對偏移量,以反映32位模式下堆棧插槽的長度為4個字節的事實。 我還更改了代碼以使用EDX而不是EBX,因為在32位C調用約定中,該函數需要保留EBX寄存器,而EDX(如16位C調用約定中的BX)則不需要。
在此特定情況下,SP和BP可能為0。 但是請注意,SP和BP分別是RSP和RBP的最低16位四分之一,因此堆棧指針實際上不是0。
將參數從.c傳遞到.asm的另一種方法是使用“ fastcall”約定,該約定使您可以在寄存器CX
和DX
傳遞兩個參數(實際上是ECX
和EDX
,但在代碼中使用16位寄存器)。 接下來是在VS 2013中測試的簡短示例,它將兩個int(2,5)發送給asm函數,並且該函數返回這些值的相加(7):
第一.cpp
#include "stdafx.h"
extern "C" int __fastcall second(int,int); // ◄■■ KEYWORDS "C" AND __FASTCALL.
int _tmain(int argc, _TCHAR* argv[])
{
short int result = second(2,5); // ◄■■ "RESULT" = 7.
return 0;
}
第二個asm
.model small
.code
public @second@8 ◄■■ NOTICE THE @ AND THE 8.
@second@8 proc near ◄■■ NOTICE THE @ AND THE 8.
mov ax,cx ◄■■ AX = 2.
add ax,dx ◄■■ AX + 5 (RETURN VALUE).
ret
@second@8 endp ◄■■ NOTICE THE @ AND THE 8.
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.