我的一次作業,希望對學習彙編的朋友有用。 (9千字)

看雪資料發表於2015-11-15

關於Turbo C 2.0中讀取零位元組檔案的研究
                dOSKEY lEE
    在Turbo C 2.0(下簡稱TC)中讀取零位元組檔案可以讀取出資料嗎?我做了以下研究:用TC寫一個簡單的讀取檔案的程式,然後讓其讀取一個零位元組的檔案。首先我們研究用fread讀取資料。稍後我們將研究用fgetc讀取資料。以下研究都不判斷檔案結束(EOF)。

原始碼:
#include <stdio.h>
#define BYTE unsigned char        /*定義位元組型*/

#define BUFFERLENGTH 255        /*緩衝大小*/
#define INPUTFILE "EMPTY.BIN"  /*目標檔案的檔名*/

int main(void)
{
    BYTE bBuff[BUFFERLENGTH];    /*資料緩衝*/
    FILE *pInputFile;            /*檔案指標*/
    int nReadItem;                /*讀取專案的總數*/
    int i;                        /*迴圈控制變數*/

    pInputFile=fopen(INPUTFILE,"r+b");    /*以“只讀、二進位制”的方式開啟檔案*/
    if(!pInputFile)                        /*檔案是否開啟成功,不成功便提示推出返回1*/
    {
        printf("Error! Cannot open target file.");
        return 1;
    }

/*從檔案裡讀取資料,共讀取一個專案,每個專案255個位元組*/
    nReadItem=fread(bBuff,BUFFERLENGTH,1,pInputFile);
    if(nReadItem>0)    /*是否順利從檔案讀取出專案*/
    {
        printf("Read %d item(s) from target file.\n",nReadItem);    /*讀取的專案數*/

/*讀取的位元組數=(專案數*255)*/
        printf("Read %d byte(s) from target file.\n",nReadItem*BUFFERLENGTH);    

        printf("Data:\n");    /*提示開始輸出資料*/

/*由於0取模任何數等於0,無法控制格式,所以從1開始計數*/
        for(i=1;i<=BUFFERLENGTH;i++)
        {
/*輸出資料,由於控制變數從1開始,故下標減一*/
            printf("0x%02X ",bBuff[i-1]);
            if(i%15==0)    /*控制歌頌,每行輸出15個資料*/
                printf("\n");
        }
    }
    else    /*從檔案不能讀取資料*/
        printf("Sorry! Cannot read data from target file.");

    fclose(pInputFile);    /*關閉檔案指標*/
    return 0;    /*正常結束,返回0*/
}

將其在TC中編譯。然後找到一個零位元組檔案,將它更名為EMPTY.BIN。然後在DOS提示符號下鍵入test1回車。輸入如下:
C:\>test1
Sorry! Cannot read data from target file.
檔案被成功開啟,但是沒有任何資料被讀取。然後將EMPTY.BIN改名為A.BIN。找一個大小為254位元組的檔案,將起檔名改為EMPTY.BIN,然後再在DOS提示符號下鍵入test1回車。由於在程式中一次讀取的資料是255位元組。所以有和上面相同的結果。如果EMPTY.BIN檔案的大小等於255位元組或者大於255位元組,那麼就會有如下的輸出結果:
C:\>test1
Read 1 item(s) from target file.
Read 255 byte(s) from target file.
Data:
0x80 0x09 0x00 0x07 0x54 0x45 0x53 0x54 0x31 0x2E 0x43 0x8E 0x88 0x1D 0x00
0x00 0x00 0x19 0x54 0x43 0x38 0x36 0x20 0x42 0x6F 0x72 0x6C 0x61 0x6E 0x64
0x20 0x54 0x75 0x72 0x62 0x6F 0x20 0x43 0x20 0x32 0x2E 0x30 0x20 0xFC 0x88
0x0F 0x00 0x00 0xE9 0xF5 0x59 0x7E 0x2D 0x07 0x54 0x45 0x53 0x54 0x31 0x2E
0x43 0x9E 0x88 0x17 0x00 0x00 0xE9 0x00 0x10 0x1D 0x11 0x0F 0x44 0x3A 0x5C
0x54 0x43 0x32 0x30 0x5C 0x53 0x54 0x44 0x49 0x4F 0x2E 0x48 0x03 0x88 0x18
0x00 0x00 0xE9 0x00 0x10 0x1D 0x11 0x10 0x44 0x3A 0x5C 0x54 0x43 0x32 0x30
0x5C 0x53 0x54 0x44 0x41 0x52 0x47 0x2E 0x48 0xBF 0x88 0x06 0x00 0x00 0xE5
0x01 0x00 0x00 0x8C 0x88 0x06 0x00 0x00 0xE5 0x01 0x09 0x00 0x83 0x88 0x0A
0x00 0x00 0xE3 0x1A 0x00 0x02 0x00 0x15 0x08 0x04 0x4E 0x88 0x48 0x00 0x00
0xE2 0x00 0x05 0x6C 0x65 0x76 0x65 0x6C 0x04 0x00 0x05 0x66 0x6C 0x61 0x67
0x73 0x0A 0x00 0x02 0x66 0x64 0x02 0x00 0x04 0x68 0x6F 0x6C 0x64 0x08 0x00
0x05 0x62 0x73 0x69 0x7A 0x65 0x04 0x00 0x06 0x62 0x75 0x66 0x66 0x65 0x72
0x1A 0x00 0x04 0x63 0x75 0x72 0x70 0x1A 0x00 0x06 0x69 0x73 0x74 0x65 0x6D
0x70 0x0A 0x80 0x05 0x74 0x6F 0x6B 0x65 0x6E 0x04 0xAC 0x88 0x08 0x00 0x00
0xE3 0x19 0x00 0x10 0x00 0x1E 0x46 0x88 0x0A 0x00 0x00 0xE3 0x18 0x00 0x02
0x00 0x15 0x19 0x04 0x3F 0x88 0x09 0x00 0x00 0xE3 0x1B 0x00 0xFF 0x00 0x1A

C:\>

反彙編:
_main: int main(void)
cs:01FA 55            push  bp    ;保護原堆疊暫存器
cs:01FB 8BEC          mov    bp,sp    ;堆疊暫存器初始化
cs:01FD 81EC0201      sub    sp,0102    ;堆疊指標初始化
cs:0201 56            push  si    ;保護SI
cs:0202 57            push  di    ;保護DI
TEST1#14:  pInputFile=fopen(INPUTFILE,"r+b");
cs:0203 B89E01        mov    ax,019E    ;取得引數一"r+b"的指標
cs:0206 50            push  ax    ;壓入引數一
cs:0207 B89401        mov    ax,0194    ;取得引數二INPUTFILE,即"EMPTY.BIN"的指標
cs:020A 50            push  ax    ;壓入引數二
cs:020B E8DC05        call  _fopen    ;呼叫fopen開啟檔案並取得檔案指標,儲存到AX
cs:020E 59            pop    cx    ;清除引數二
cs:020F 59            pop    cx    ;清除引數一
cs:0210 8BF8          mov    di,ax    ;將檔案指標儲存到DI,以便下面的比較操作
TEST1#15:  if(!pInputFile)
cs:0212 0BFF          or    di,di    ;檔案指標是否為空
cs:0214 750E          jne    #TEST1#21 (0224)    ;如果不為空便跳轉到224H
TEST1#17:  printf("Error! Cannot open target file.");
cs:0216 B8A201        mov    ax,01A2    ;取得引數一"Error! Cannot open target file."的指標
cs:0219 50            push  ax    ;壓入引數一
cs:021A E8C413        call  _printf    ;呼叫printf
cs:021D 59            pop    cx    ;清除引數一
TEST1#18:  return 1;
cs:021E B80100        mov    ax,0001    ;將返回值1儲存到AX
cs:0221 E98600        jmp    #TEST1#39    ;跳轉到程式結束處並返回AX中的值,即1
TEST1#21:  nReadItem=fread(bBuff,BUFFERLENGTH,1,pInputFile);
cs:0224 57            push  di    ;壓入引數一,檔案指標
cs:0225 B80100        mov    ax,0001    ;取得專案數
cs:0228 50            push  ax    ;壓入引數二,專案數
cs:0229 B8FF00        mov    ax,00FF    ;取得專案大小,即緩衝大小
cs:022C 50            push  ax    ;壓入引數三,專案大小
cs:022D 8D86FEFE      lea    ax,[bp-0102]    ;取得緩衝區首地址(在堆疊中)
cs:0231 50            push  ax    ;壓入引數四,緩衝區首地址
cs:0232 E8A00D        call  _fread    ;呼叫fread讀取檔案資料,返回的是已經讀取的專案數
cs:0235 83C408        add    sp,0008    ;堆疊指標向後偏移8
cs:0238 8946FE        mov    [bp-02],ax    ;將已讀取的專案數儲存到變數中(在堆疊中)
TEST1#22:  if(nReadItem>0)
cs:023B 837EFE00      cmp    word ptr [bp-02],0000    ;已讀取的專案數是否為0
cs:023F 7E58          jle    #TEST1#35 (0299)    ;如果小於等於0(即IF條件不成立),跳轉到299H處,處理不成立
TEST1#24:  printf("Read %d item(s) from target file.\n",nReadItem);
cs:0241 FF76FE        push  word ptr [bp-02]    ;壓入引數一,已讀取專案數
cs:0244 B8C201        mov    ax,01C2    ;取得引數二,"Read %d item(s) from target file.\n"的指標
cs:0247 50            push  ax    ;壓入引數二
cs:0248 E89613        call  _printf    ;呼叫printf
cs:024B 59            pop    cx    ;清除引數一
cs:024C 59            pop    cx    ;清除引數二
TEST1#25:  printf("Read %d byte(s) from target file.\n",nReadItem*BUFFERLENGTH);
cs:024D 8B46FE        mov    ax,[bp-02]    ;取得已讀取的專案數(nReadItem),被乘數
cs:0250 BAFF00        mov    dx,00FF        ;取得專案大小,即緩衝大小(BUFFERLENGHT),乘數
cs:0253 F7E2          mul    dx    ;做乘運算,積儲存在AX中
cs:0255 50            push  ax    ;壓入引數一,已讀取的專案數和緩衝大小的乘積
cs:0256 B8E501        mov    ax,01E5    ;取得引數二"Read %d byte(s) from target file.\n"的指標
cs:0259 50            push  ax    ;壓入引數二
cs:025A E88413        call  _printf    ;呼叫printf
cs:025D 59            pop    cx    ;清除引數二
cs:025E 59            pop    cx    ;清除引數一
TEST1#26:  printf("Data:\n");
cs:025F B80802        mov    ax,0208    ;取得引數一"Data:\n"的指標
cs:0262 50            push  ax    ;壓入引數一
cs:0263 E87B13        call  _printf    ;呼叫printf
cs:0266 59            pop    cx    ;清除引數一
TEST1#27:  for(i=1;i<=BUFFERLENGTH;i++)
cs:0267 BE0100        mov    si,0001    ;迴圈控制變數i的初始化
cs:026A EB25          jmp    0291    ;跳轉到迴圈尾部,準備第一次迴圈
TEST1#29:  printf("0x%02X ",bBuff[i-1]);
cs:026C 8A82FDFE      mov    al,[bp


宣告:該文觀點僅代表作者本人,轉載請註明來自看雪專欄
最新評論 (0)
登入後即可評論

相關文章