2021年5月16日 星期日

TI Launchpad MSP430 with PIR(紅外線感應器)

緣起:
最近聽到有人的辦公室座位坐在靠走道人來人往,隱私被看光光,所以想研究能夠偵測有人靠近的"紅外線感應器(PIR)",將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

系統架構: 
MSP430+PIR當偵測到有人靠近就送出一個字元資料'@'透過rs232傳輸到個人電腦PC端, PC端寫一個專門接收rs232(COM3)訊號的程式(ezPIR),當ezPIR程式收到rs232介面傳過來的資料, 馬上模擬鍵盤向作業系統送出一個"視窗鍵+D(將所有工作視窗縮小並顯示桌面)", 網購的PIR型號AM312如下:

所有程式碼下載連結:
https://drive.google.com/file/d/1FKPrjo4tR3qEZACkTcZNQEiyiAl1ANcX/view?usp=sharing


2021年1月31日 星期日

Win32視窗程式_WM_CLOSE_trace code_第二彈

緣起:
最近在研究Win32平台的組合語言, 想看一下Win32API視窗程式在使用者按下右上角紅色叉叉觸發WM_CLOSE訊息後,是怎樣關閉整個視窗的,將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

過程:
1.開啟Visual Studio 201x->新增專案->Visual C++ ->Win32專案->取名為traceWM_CLOSE->完成,
2.修改traceWM_CLOSE.cpp程式,在UpdateWindow(hWnd);這行的底下加入底下的程式:
   PostMessage(hWnd,WM_CLOSE,0,0);
   p.s.在主訊息迴圈那設中斷點導致無法按視窗右上角的紅色叉叉,只好用程式送WM_CLOSE訊息,

3.另外將return DefWindowProc(hWnd, message, wParam, lParam);這行註解,改為底下的程式:
   int LRESULT=DefWindowProc(hWnd, message, wParam, lParam);
   return LRESULT;

4.先在PostMessage()這行設中斷點, 按F5, 
5.取消中斷點, 在GetMessage()跟DispatchMessage()這兩行設中斷,不斷按F5直到msg數值為0x10,
6.在WndProc()內第1行及return DefWindowProc()設中斷,不斷按F5,同時觀察"呼叫堆疊"的變化如下:
   WM_CLOSE(0x10)
     ->產生WM_XXX(0x90)
      ->WM_WINDOWPOSCHANGING(0x46)
        ->WM_WINDOWPOSCHANGED(0x47) 此時視窗已消失,但"工作管理員"仍顯示該行程!
          ->WM_IME_SETCONTEXT(0x281)
            ->WM_IME_NOTIFY(0x282)
              ->WM_DESTROY(0x2) 此時先在PostQuitMessage(0);設中斷點,按F5可看到跳到中斷點這,
               ->WM_NCDESTROY(0x82), 此時已產生WM_QUIT於系統訊息queue,
7.程式到此才處理完WM_CLOSE訊息,返回主訊息迴圈,可觀察msg仍維持0x10(WM_CLOSE),這時再GetMessage()就得到WM_QUIT(0x12)而跳出迴圈, 然後return結束整個程式,此時在工作管理員已看不到這個行程!

結果:
關於以上過程各步驟的精彩截圖, 請到底下這個網址下載WORD檔來觀看:
https://drive.google.com/file/d/1eiJcAJ3KfBOps49S63CGp6kN6zyFLXIY/view?usp=sharing

2021年1月23日 星期六

C語言_main函數_trace code

緣起:
最近在研究Win32平台的組合語言, 想看一下C語言的底層長甚麼樣子,就拿最簡單的程式來看:
  int main( )
 {
 }
將心得寫成此篇blog.本篇blog有不足之處,日後補上,轉貼或引用本篇文章, 不必交代出處!

過程:
1.開啟Visual Studio 201x -> 新增專案 -> Visual C++ -> Win32主控台應用程式 -> 勾選空專案,
2.方案總管->原始程式檔->加入->新增項目->C++檔(.cpp)->檔名為Source.cpp
3.在Source.cpp內輸入下列程式碼:
  int main()
 {
 }

4.在int main()這行前面設定中斷點,按F5開始偵錯, 切到"反組譯碼", 按F11一步一步執行如下,特別注意圖上右邊三塊粉紅色區塊跟粉紅色字的區塊,最下面的區塊表示最早看到的呼叫堆疊, 只要F11按得夠久就可看到粉紅色字的區塊顯示的ExitProcess函數(VC++2010 express可看到,VS2015則看不到,那些是從google找到別人使用VS2015看到的造成runtime error當時的callStack),等該函數執行完就結束整個行程(process)[註1][註2]:

5.上圖中執行到ret(pop下一行指令的位址存到eip)後回到上一層函數內,上圖跟下圖是分兩次trace,所以stack內存的位址會不同:

6.將stack看到的參數2位址006da008打入"記憶體"內的位址這欄內按enter,解析如下:

7.將stack看到的參數3位址00687cc0打入"記憶體"內的位址這欄內按enter,解析如下:

註1:第四個步驟的附圖中提到cc cc cc cc共192Bytes的區塊是當作stack預留的guard band是錯誤的,
       因為隨後自行trace函數main內有程式碼的案例, 發現這區塊被拿來存main()內宣告的變數/指
       標,請見下圖:

註2.除了記憶體視窗/暫存器視窗/反組譯碼視窗以外,VS201x系列還提供命令視窗可輸入指令也可
       看到記憶體內容/暫存器/反組譯碼,這種方式的優點:可看出程式執行前後差異,缺點:常打指令,
       詳細指令請參考微軟網站:
https://docs.microsoft.com/zh-tw/visualstudio/ide/reference/list-memory-command?view=vs-2019