1. 程式人生 > >彙編綜合研究5 實現printf函式

彙編綜合研究5 實現printf函式

根據綜合研究5showchar()函式,可以瞭解引數都是由棧傳遞的,所要傳遞引數的個數也可以由棧傳遞。那麼printf函式要輸出的引數肯定也是由棧傳遞。另外一點就是printf函式肯定有某種資訊,這種資訊記錄了需要列印的個數。

main()

{

printf("%c,%d/n",'a',2);

}

函式如上,編譯連線後用反彙編檢視cs:01fa

能看出來,列印的引數‘a’,2都是由棧傳遞。入棧的時候還有一個未知資訊:mov ax0194

Pushax

0194肯定不是我們需要列印的引數,那麼它就是printf函式自己新增的。根據上面的假設,printf自己能夠獲取資訊,得知所要列印引數的個數。這個資訊應該也放在記憶體的某個位置。那麼會不會

0194就是那個位置的IP

檢視一下:

在資料段的ip=0194位置處,存放了這些資訊。可以肯定printf函式就是從這個位置得到資訊,確定當前要列印的引數型別的。

再修改一下main函式,檢視一下:

main()

{

printf("%c,%d,%s,%c/n",'a',2,"hello",'d');

}

倒數第二個列印引數是個字串,入棧的01a1應該是字串的首地址。檢視一下ds0194

Ds01a1正好是“hello“的地址。這樣我們能夠得知:

printf("%c,%d,%s,%c/n",'a',2,"hello",'d');printf();裡面有字串“%C%d%s%c/n

,hello”,還有char型‘a’,‘d’,int2.這裡面的int型和char型資料被放到棧裡,字串型資料放在了DS0194位置處。並且DS0194處,字串以0結束。

自己寫printf函式。想法:

列印位置:

dh=行,dl=列。

1printf("%c,%d,%s,%c/n",'a',2,"hello",'d')為例。

"%c,%d,%s,%c/n"裡找要列印的資訊屬性。這個字串的長度也能求出來。(0AH是‘/n’的ASICⅡ)

2)檢測"%c,%d,%s,%c/n",如果當前是%C則打印出字元,是%D列印int型資料,是%S則列印字串。是‘/n’,行號加1

如果是

int資料,如234,要用逐位摸除方法,轉換程字元‘2’,‘3’,‘4’再列印。因為視訊記憶體上顯示的都是字元型。

 (3)檢測到非上述資訊,直接列印。

程式如下:


void print(char *,...);
main()
{
 clrscr();
 printf("%d,%c",123,'x');
 print("%c,ccc%s,%d/n%d,%c",'a',"hello",1123,5,'d');

}
void print(char *p,...)
{

    int count=0;      /* the station of int and char used in stack */
    int data=0;
    int signal=0;

    char *buffer=(char *)malloc(10);
    char *str=0;
    int dh=10;
    int dl=0;

    while(*p!=0)
   {

 if(*p=='%' && *(p+1)=='c')
 {
    *(char far *)(0xb8000000+160*dh+2*dl)=*(int *)(_BP+6+count+count);
           count++;
     dl=dl+1;
    p+=2;
 }
      else if(*p=='%' && *(p+1)=='d')
        {
           data=*(int *)(_BP+6+count+count) ;
    count++;
    p+=2;
    if(data==0){  *(char far *)(0xb8000000+160*dh+2*dl)=0x30; dl+=1;}
    if(data<0) { signal=1; data=-data; }
           buffer[0]=0;
           while(data!=0)
           {
               buffer++;
               *buffer=data%10+0x30;
               data=data/10;
           }
           while(*buffer!=0)
           {
             if(signal==1)
             {
        *(char far *)(0xb8000000+160*dh+2*dl)='-';
        dl++;
               signal=0;
             }
        *(char far *)(0xb8000000+160*dh+2*dl)=*buffer;
        buffer--;
        dl++;
    }

 }
 else if(*p=='%' && *(p+1)=='s')
 {
/*這裡進行一個型別轉化,把從棧裡取得的int型資料,轉換為char型指標*/   

str=(char *)*(int *)(_BP+6+count+count);

    count++;
    while(*str!=0)
    {
      *(char far *)(0xb8000000+160*dh+2*dl)=*str;
       str++;
       dl++;
    }
    p+=2;

 }
 else if(*p=='/n')
 {
     dh++;
     dl=0;
     p++;
 }

        else
        {
  *(char far *)(0xb8000000+160*dh+2*dl)=*p;
   dl++;
   p++;
        }

   }
}

相關推薦

彙編綜合研究5 實現printf函式

根據綜合研究5的showchar()函式,可以瞭解引數都是由棧傳遞的,所要傳遞引數的個數也可以由棧傳遞。那麼printf函式要輸出的引數肯定也是由棧傳遞。另外一點就是printf函式肯定有某種資訊,這種資訊記錄了需要列印的個數。 main() { printf("%c,%

12 裸板實現printf函式

裸板實現printf函式 在uboot上,首先uart第0個控制器已經被uboot驅動好了。 uart控制器負責資料的收發,我們只要把資料交給uart控制器發出,和從uart控制器裡把資料取回來即可。 也就是我們只要找到相應的uart控制器的配置暫存器即可。 檢視

用可變引數列表模擬實現printf函式

用可變引數列表實現printf函式要實現printf函式,我們首先應該獲取printf函式中由雙引號中的字串,若遇到不是%的字元,我們應該直接將其輸出,若遇到%,我們應該判斷它後面是什麼字元,這裡先只考慮%c,%s的情況,如果是%c那麼我們應該將讀到的字元輸出來,若為%s,應

【C語言】用可變引數列表實現printf函式

//用可變引數列表實現printf函式 #include <stdio.h> #include <stdarg.h> void my_printf(const char *st

模擬實現printf函式,可變引數列表例項

首先可通過CSDN檢視printf函式原型等資訊 實現功能: Print formatted output to the standard output stream. 即格式化輸出並

C語言實現printf函式,即引數可變函式原理

我們在C語言程式設計中會遇到一些引數個數可變的函式,例如printf() 這個函式,它的定義是這樣的: int printf( const char* format, ...); 它除了有一個引數format固定以外,後面跟的引數的個數和型別是 可變的,例如我們可以有以下不

用可變引數列表模擬實現printf函式,可完成下面的功能

【問題描述】:模擬實現printf函式,可完成下面的功能//能完成下面函式的呼叫。//print("s ccc d.\n","hello",'b','a','t',100);//函式原型://print

C語言:模擬實現printf函式

4.1.模擬實現printf函式,可完成下面的功能 能完成下面函式的呼叫。  print("s ccc d.\n","hello",'b','i','t',100);  函式原型:  print(char *format, ...)  程式碼如下: #include &l

05 printf函式可變引數的實現原理之彙編分析

如實現一個像printf函式格式的函式: test.c void myprintf(char *line, ...) // line指標變數是區域性變數,在棧裡分配空間 { printf(line); //呼叫printf時,r0存放字串地

自己實現printf函式

根據上一篇中的  《可變引數列表(非格式化控制)》,今天繼續學習: 自己寫一個函式實現printf功能。 1.自己實現的printf函式 #include <stdio.h> #include <stdarg.h> void my_printf(c

Mosquitto-1.5.4原始碼分析,PUBLISH的實現函式跳轉關係

客戶端向伺服器傳送資料包(packet)時,首先將資料包放到改傳送佇列中,並不真實發送資料,而是傳送資料就緒訊號,等待loop事件迴圈呼叫的函式db__message_write根據網路連線情況來處理髮送請求;該佇列為單鏈表儲存結構,每次有新資料包需要傳送時,將新資料包插入到連結串列尾部;真正傳

Windows下DEVC++ 5.11 的printf函式對引數的執行順序

printf函式為其引數建立一個[棧],從右到左將引數壓入棧,再從棧內將裡面的元素依次列印。 函式舉例 #include <stdio.h> int p(int a) { print

51微控制器實現scanf和printf函式

最開始學習C語言時,使用printf和scanf進行格式化輸入輸出十分方便。 學習微控制器有很長時間了,之前要再螢幕上顯示一個變數或者通過串列埠傳出一些變數值觀測的話,需要進行一系列的取餘取整運算,很是麻煩。 最近又研究了一下keil中針對printf和scanf的實現機理,做了一些改動,實現了標準格式化輸

No.5 MYSQL實現 RANK函式排序功能

 MySQL中不存在類似於SQL Server或Orcal中的rank()函式來得到排名。所以我們需要手動來時先這個函式,先看一下應用場景: 查詢每門課成績最好的前兩名: select r.cid,score,rank from (select tmp.cid,tmp.sc

王爽組合語言綜合研究-函式如何接收不定數量的引數

1、c語言如何傳遞引數 編寫這樣一個程式試驗 void showchar(char a,int b); main() { showchar('a',2); } void showchar(char a,int b) { *(char far *)(0xb8000000 + 160*10 + 80

C語言編寫log檔案以及printf函式實現原理

C語言編寫log檔案以及printf函式實現原理        在系統除錯中通過在檔案系統裡寫log日誌是一個長期分析系統執行的好方法。做系統除錯應該養成這個習慣,可以方便的監控系統可能出現的各種異常。        今天學習下log日誌的書寫方法。Log一般可以分為以下4種

自己實現的簡單Printf函式

注意: 1.*pStr != '\0'  2.sprintf正確使用 3.double不能用float否則會溢位非法訪問 4. *pFormat != '\0' 5.pFormat 不能用pTempFormat 原始碼: #include <stdio.h> #

面試例題5—感知器實現and函式

用感知器實現and函式 參考部落格:https://www.zybuluo.com/hanbingtao/note/433855點選開啟連結 and 運算時一個二元運算,它的真值表如下: x1 x2 y 0 0 0 0 1 0 1 0 0 1 1 1 Python: cl

用可變引數列表實現簡單的printf函式

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<stdarg.h> void print_num(int n) { if (

【c語言】用可變引數列表實現一個簡化的printf函式

//實現一個簡化的printf函式。 #include <stdarg.h> #include <string.h> void my_printf(const char *str,...) { va_list arg; //準備訪問可變引