根據綜合研究5的
showchar
()函式,可以了解引數都是由棧傳遞的,所要傳遞引數的個數也可以由棧傳遞。那麼
printf
函式要輸出的引數肯定也是由棧傳遞。另外一點就是
printf
函式肯定有某種資訊,這種資訊記錄了需要列印的個數。
main()
函式如上,編譯連線後用反彙編檢視
cs:01fa
能看出來,列印的引數『a』,
2都是由棧傳遞。入棧的時候還有乙個未知資訊:
mov ax
,0194
pushax
0194
肯定不是我們需要列印的引數,那麼它就是
printf
函式自己新增的。根據上面的假設,
printf
自己能夠獲取資訊,得知所要列印引數的個數。這個資訊應該也放在記憶體的某個位置。那麼會不會
0194
就是那個位置的ip?
檢視一下:
在資料段的
ip=0194
位置處,存放了這些資訊。可以肯定
printf
函式就是從這個位置得到資訊,確定當前要列印的引數型別的。
再修改一下
main
函式,檢視一下:
main()
倒數第二個列印引數是個字串,入棧的
01a1
應該是字串的首位址。檢視一下ds:
0194 ds
:01a
1正好是「
hello
「的位址。這樣我們能夠得知:
printf("%c,%d,%s,%c/n",'a',2,"hello",'d');printf();
裡面有字串「%c,
%d,%s,
%c/n」,
「hello
」,還有
char型『a
』,『d
』,int型2.
這裡面的
int型和
char
型資料被放到棧裡,字串型資料放在了ds:
0194
位置處。並且ds:
0194
處,字串以
0結束。
自己寫printf
函式。想法:
列印位置:
dh=行,dl=列。
(1)以
printf("%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()
void print(char *p,...)
else if(*p=='%' && *(p+1)=='d')
if(data<0)
buffer[0]=0;
while(data!=0)
while(*buffer!=0)
*(char far *)(0xb8000000+160*dh+2*dl)=*buffer;
buffer--;
dl++;}}
else if(*p=='%' && *(p+1)=='s')
p+=2;
}else if(*p=='/n')
else}}
組合語言綜合研究 使用暫存器
1 使用暫存器程式設計 main 函式是c 語言編寫程式的入口函式,但是 main 中的第一條語句並不是程式中被執行的第一條指令,還有很多其它語句。為了研究我們的程式編譯後的語句,首先要找 main 函式的位置,可以通過下邊的程式獲得 main 函式的偏移位址 main 函式中printf 語句表示...
王爽《組合語言》綜合研究實驗5 (3)
實現乙個簡單的printf函式,只需支援 c d 即可 這邊先看一下c中printf函式的簡單例子的彙編 這邊我們用綜合研究中所搭建的簡介c開發環境寫乙個簡單的printf例子 生成相應的printft.exe可執行檔案,在cmd下用debug進行除錯,得到對應的彙編指令如下 printf函式本身的...
MDK環境下stm32實現printf函式
printf雖然是c語言的標準函式,但是是針對有stdin,stdout裝置的系統的,在嵌入式平台上是沒有標準的stdin,stdout的,需要對映到串列埠後某個輸出物件的,而嵌入式平台各不相同,如果又沒有作業系統的支援,就只能靠自己實現了,因此stm32下的printf不在標準庫里,而在定製的庫里...