在汇编中定义一个过程,如下段:
.
.
.128  WaitWhileBusy proc
129    MOV  EBX, 100000
130    MOV  DX, dwBaseAddress
131    ADD  DX, 7
132  @LoopWhileBusy:
133    DEC  EBX
134    CMP  EBX, 0
135    JZ   @Timeout
136    in   AL, DX
137    TEST AL, btBusy
138    JNZ  @LoopWhileBusy
139    JMP  @DriveReady
140  @Timeout:   // 超时,直接退出
141    JMP  @LeaveRing0
142  @DriveReady:
143    RET
144    ENDP   // End of WaitWhileBusy Procedure
.
.
.编译后提示错误:
1、Undeclared identifier: 'WaitWhileBusy'       //第128行
2、Invalid combination of opcode and operands   //第137行
3、Undeclared identifier: 'ENDP'                //第144行请问各位高手,此问题如何解决?谢谢

解决方案 »

  1.   

    按你提供的片段, 只能写个如下的能通过编译的代码供你参考了:var
      dwBaseAddress : Word;const
      btBusy = 1;procedure MyASM;
    begin
      asm
        @WaitWhileBusy:
          MOV  EBX, 100000
          MOV  DX, dwBaseAddress
          ADD  DX, 7
        @LoopWhileBusy:
          DEC  EBX
          CMP  EBX, 0
          JZ   @Timeout
          in   AL, DX
          TEST AL, btBusy
          JNZ  @LoopWhileBusy
          JMP  @DriveReady
        @Timeout:   // 超时,直接退出
          JMP  @LeaveRing0
        @DriveReady:
          RET
        @LeaveRing0:
      end;
    end;
      

  2.   

    也就是说,Delphi中的汇编段不能定义过程吗?
      

  3.   

    Delphi中是有过程和函数的定义的,所以宏汇编中的proc endp之类的自然就不需要了。连TASM中都可以不要这个。
    另外你可以写纯汇编过程,即以procedure asm end定义的过程,不需要procedure begin asm end end这种结构。
    还有在BASM过程中是不需要写ret的,最后那个end就指示编译器自动生成ret、ret n这种返回指令。
      

  4.   

    实际上我是想把下面这段获取硬盘序列号的C++程序转换为Delphi程序,
    在网上有很多获取硬盘序列号的资料,但绝大多数都只能在NT环境下有效,在9X下就不行了,下面这段程序在NT和9X下都行,就是在转为Delphi的过程中遇到很多问题,
    希望jadeluo(秀峰) 或其他高手帮忙转一下,谢谢。//---------------------------------------------------------------------------#include <vcl.h>
    #include <WinIOCtl.h>
    #include <stdio.h>
    #pragma hdrstop
    #pragma inline#include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------// 辅助函数
    char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    // Windows 9X函数
    void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
            BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);
    //---------------------------------------------------------------------------// ConvertToString
    char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    {
    static char szResBuf[1024];
    int nIndex = 0;
    int nPosition = 0; // Each integer has two characters stored in it backwards
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    {
    // Get high BYTE for 1st character
    szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    nPosition++; // Get low BYTE for 2nd character
    szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
            nPosition++;
    }    // End the string
    szResBuf[nPosition] = '\0';    // Cut off the trailing blanks
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
            szResBuf[nIndex] = '\0'; return szResBuf;
    }
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    // Windows 95/98/ME 代码
    //---------------------------------------------------------------------------
    // ReadPhysicalDriveOnW9X
    void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    {
    WORD wOutData[256];
        SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
        // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
        // 避免蓝屏的出现。(期待高人能指出原因)
        for(int nDrive = 0; nDrive < 8; nDrive++)
        {
            WORD dwBaseAddress;
            BYTE btMasterSlave;         // Master Or Slave
            bool bIsIDEExist;
            bool IsDiskExist;        switch(nDrive / 2)
            {
                case 0: dwBaseAddress = 0x01F0; break;
                case 1: dwBaseAddress = 0x0170; break;
                case 2: dwBaseAddress = 0x01E8; break;
                case 3: dwBaseAddress = 0x0168; break;
            }        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);        // 进入Ring0
            ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
                    bIsIDEExist, IsDiskExist, wOutData);
        }    // 开始读取
        for(int nDrive = 0; nDrive < 8; nDrive++)
        {
            WORD dwBaseAddress;
            BYTE btMasterSlave;         // Master Or Slave
            bool bIsIDEExist;
            bool bIsDiskExist;
            switch(nDrive / 2)
            {
                case 0: dwBaseAddress = 0x01F0; break;
                case 1: dwBaseAddress = 0x0170; break;
                case 2: dwBaseAddress = 0x01E8; break;
                case 3: dwBaseAddress = 0x0168; break;
            }        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);        // 进入Ring0
            bIsIDEExist  = false;
            bIsDiskExist = false;
            ZeroMemory(wOutData, sizeof(wOutData));        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
                    bIsIDEExist, bIsDiskExist, wOutData);        if(bIsIDEExist && bIsDiskExist)
            {
                DWORD dwDiskData[256];
                char  szSerialNumber[21];
                char  szModelNumber[41];            for(int k=0; k < 256; k++)
                    dwDiskData[k] = wOutData[k];            // 取系列号
                ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
                strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));            // 取模型号
                ZeroMemory(szModelNumber, sizeof(szModelNumber));
                strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));            pSerList->Add(szSerialNumber);
                pModeList->Add(szModelNumber);
            }
        }
        SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    }
      

  5.   

    //---------------------------------------------------------------------------
    // 为防止不负责任的转载者,在此注明原出处信息,请见谅。
    // 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
    //---------------------------------------------------------------------------
    // ReadPhysicalDriveOnW9X_Ring0()
    //
    // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    //---------------------------------------------------------------------------
    void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
            BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    {
        BYTE  btIDTR1[6];
        DWORD dwOldExceptionHook;
        const int nHookExceptionNo = 5;    BYTE  btIsIDEExist = 0;
        BYTE  btIsDiskExist = 0;
        WORD  wOutDataBuf[256];    BYTE  btIsFirst = (BYTE)bIsFirst;    const BYTE btBit00 = 0x01;
        // const BYTE btBit02 = 0x04;
        const BYTE btBit06 = 0x40;
        const BYTE btBit07 = 0x80;
        // const BYTE btERR  = btBit00;
        const BYTE btBusy = btBit07;
        const BYTE btAtaCmd   = 0xEC;
        const BYTE btAtapiCmd = 0xA1;    __asm
        {
            // 必须先执行这条语句
            JMP EnterRing0        // 定义过程
            // 等待IDE设备直到其不为忙为止
            WaitWhileBusy proc        MOV  EBX, 100000
            MOV  DX, dwBaseAddress
            ADD  DX, 7        LoopWhileBusy:        DEC  EBX
            CMP  EBX, 0
            JZ   Timeout
            in   AL, DX
            TEST AL, btBusy
            JNZ  LoopWhileBusy
            JMP  DriveReady        // 超时,直接退出
            Timeout:
            JMP  LeaveRing0
            DriveReady:
            RET
            ENDP   // End of WaitWhileBusy Procedure        // 设置主盘和从盘标志
            SelectDevice proc        MOV  DX, dwBaseAddress
            ADD  DX, 6
            MOV  AL, btMasterSlave        out  DX, AL
            RET ENDP  // End of SelectDevice Procedure        // 向IDE设备发送存取指令
            SendCmd proc        MOV DX, dwBaseAddress
            ADD DX, 7
            MOV AL, BL // BL是主从盘标识,在过程外设置
            out DX, AL
            RET
            ENDP  // End of SendCmd Procedure        // Ring0代码
            Ring0Proc:
            PUSHAD
            // 查询IDE设备是否存在
            MOV DX, dwBaseAddress
            ADD DX, 7
            in  AL,DX        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
            CMP AL,0xFF
            JZ  LeaveRing0
            CMP AL, 0x7F
            JZ  LeaveRing0        // 设置IDE设备存在标志
            MOV btIsIDEExist, 1        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
            CALL WaitWhileBusy
            CALL SelectDevice        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
            CMP  btIsFirst, 1
            JZ   LeaveRing0        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
            CALL WaitWhileBusy        // AL的值等于cBit06时,不存在驱动器,直接返回
            TEST AL, btBit06
            JZ   LeaveRing0        // 设置驱动器存在标志
            MOV  btIsDiskExist, 1        // 发送存取端口命令
            // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
            // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
            CALL WaitWhileBusy
            CALL SelectDevice    // 设置主从盘标识
            MOV  BL, btAtaCmd      // 发送读取命令
            CALL SendCmd
            CALL WaitWhileBusy        // 检查是否出错
            MOV  DX, dwBaseAddress
            ADD  DX, 7        in   AL, DX        TEST AL, btBit00
            JZ   RetrieveInfo   // 没有错误时则读数据        // 如果出错,则进一步尝试使用ATAPI设备命令
            CALL WaitWhileBusy
    CALL SelectDevice
            MOV  BL, btAtapiCmd
            CALL SendCmd
            CALL WaitWhileBusy        // 检查是否还出错
            MOV  DX, dwBaseAddress
            ADD  DX, 7
            in   AL, DX
            TEST AL, btBit00
            JZ   RetrieveInfo   // 没有错误时则读数据
            JMP  LeaveRing0     // 如果还是出错,直接返回        // 读取数据
            RetrieveInfo:        LEA  EDI, wOutDataBuf
            MOV  ECX, 256
            MOV  DX, dwBaseAddress
            CLD        REP  INSW        // 退出Ring0代码
            LeaveRing0:        POPAD
            IRETD        // 激活Ring0代码
            EnterRing0:        // 修改中断门
            SIDT FWORD PTR btIDTR1
            MOV EAX, DWORD PTR btIDTR1 + 02h
            ADD EAX, nHookExceptionNo * 08h + 04h
    CLI        // 保存原异常处理例程入口
            MOV ECX, DWORD PTR [EAX]
            MOV CX, WORD PTR [EAX-04h]
            MOV dwOldExceptionHook, ECX        // 指定新入口
            LEA EBX, Ring0Proc
            MOV WORD PTR [EAX-04h],BX
            SHR EBX, 10h
            MOV WORD PTR[EAX+02h], BX        // 激活Ring0代码
            INT nHookExceptionNo        // 复原入口
            MOV ECX,dwOldExceptionHook
            MOV WORD PTR[EAX-04h], CX
            SHR ECX,10h
    MOV WORD PTR[EAX+02h], CX
            STI
        }
        if(!bIsFirst)
        {
            bIsIDEExist  = (bool)btIsIDEExist;
            bIsDiskExist = (bool)btIsDiskExist;
            CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
        }
    }//---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Memo1->Lines->Clear();
      Memo2->Lines->Clear();
      Memo1->Lines->Add("硬盘序列号:");
      Memo2->Lines->Add("硬盘型号:");  if (Win32Platform!=VER_PLATFORM_WIN32_NT)
    ReadPhysicalDriveOnW9X(Memo1->Lines, Memo2->Lines);
    }
    //---------------------------------------------------------------------------
      

  6.   

    请帮帮忙,谢谢而且这段代码在9X下是不需要SmartVSD的。