Tổng số lượt xem trang

Chủ Nhật, 30 tháng 6, 2013

Distinguish with " argc,char* argv[],char* envp[] "

int _tmain(int argc, _TCHAR* argv[])
{
return 0;
} Kiểu trả về của hàm là int, bộ đối quy định bắt buộc là int argc và _TCHAR* argv[]

Ý nghĩa giá trị trả về thì đã nói. Nói về ý nghĩa các biến của hàm.

int argc: argc là một biến quản lý độ dài của mảng argv[]

_TCHAR* argv[]: argv[]ở đây là một con mảng con trỏ kiểu _TCHAR(tương tự kiểu char). Nó quản lý dòng đầu tham số

đầu vào để truyền cho hàm main(sẽ nói rõ hơn trong phần dưới đây)



Bây giờ ngoài bộ đối tiêu chuẩn được quy định, chúng ta hoàn toàn có thể khai báo thêm các đối cần thiết hoặc muốn

truyền cho hàm main chẳng hạn. Ví dụ:

int _tmain(int argc, _TCHAR* argv[],int n,int myvar1,char myvar2, ...)
{
cout<<"\nGia tri integer thu nhat dc truyen cho ham la "<<n;
cout<<"\n ....";
return 0;
} Và cách truyền tham số cũng bất kì, truyền tham trị, con trỏ, tham chiếu ...

#include
using namespace ;
int n;
int _tmain(int argc, _TCHAR* argv[],int& n,int* myvar1,char myvar2, ...)
{
cout<<"\nnhap gia tri cua n ";
cin>>n;
cout<<"\n .....";
return 0;
} --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


UNIX

Một chương trình chuẩn trong UNIX

#include <iostream>
using namespace std;
int main(int argc,char* argv[],char* envp[])
{
return 0;
} argc và argv[] đã giải thích ở trên. Xem tham số char* envp[] có ý nghĩa gì? env = envirenment(môi trường). envp[] là một

mảng con trỏ kiểu char để quản lý các thông số về biến môi trường làm việc. Để dễ hiểu tôi không giải thích dài dòng

mà lấy ví dụ cụ thể để dễ trực quan.

Để biết môi trường bạn đang làm việc gồm có những tham số gì, trong hàm main chúng ta có thể dùng câu lệnh:

for(int i=0;;i++)
if(envp[i]!=NULL) cout<<"\n"<<envp[i]; Để hiểu về cơ chế hoạt động của hàm main và chức năng của argc,argv[] chúng ta biên dịch một chương trình mẫu.

Hãy tạo file 1.cpp với nội dung

#include <iostream>
using namespace std;
int main(int argc,char* argv[],char* envp[])
{
cout<<"\n Số lượng biến truyền vào từ đầu vào tiêu chuẩn "<<argc;
cout<<"\n Đó là : \n\t";
for(int i=0;i<n;i++)
cout<<"\n"<<argv[i];
cout<<"\n Các tham số môi trường mà bạn đang làm việc : \n";
for(int i=0;;i++)
if(envp[i]!=NULL) cout<<"\n"<<envp[i];

return 0;
} Chúng ta save file vừa tạo. Mở terminal và biên dịch

g++ 1.cpp # hoặc g++ 1.cpp -o 1 Sau đó chạy chương trình:

./a.out 2 "input info" "for test"# hoặc ./1 2 3 4 "input info" "for test" Tôi đang ở windows nên chưa test trực tiếp trên hệ thống UNIX được nhưng cũng có thể đọc được những thông tin thu được

trên kênh ra của chương trình:

Số lượng biến truyền vào từ đầu vào tiêu chuẩn : 4

Đó là :

argv[0] = a.out# hoặc 1

argv[1] = 2

argv[2] = input info

argv[3] = for test

Các tham số môi trường mà bạn đang làm việc :(Cái này tùy từng môi trường làm việc, tùy từng hệ thống và hệ điều hành và

chế độ làm việc hiện thời của bạn)

Một lời nho nhỏ nữa là argc nhỏ nhất là 1, vì đó là tham số tên của chương trình thực thi được truyền cho hàm.

Những hiểu biết ít ỏi này chia sẻ mong bạn hiểu hơn đôi chút về vấn đề bạn quan tâm!


Mình test một chương trình demo trên UNIX cho bạn xem để chắc chắn lại những gì mình đã giải thích ở trên:

Code chương trình:(lưu trong file 1.cpp)

#include <iostream>
using namespace std;
int main(int argc,char* argv[],char* envp[])
{
cout<<"\n\targc = "<<argc;
for(int i=0;i<argc;i++)
cout<<"\nargv["<<i<<"] = "<<argv[i];
cout<<"\n\tEnvirenment variables : ";
for(int i=0;;i++)
if(envp[i]!=NULL)cout<<"\nenvp["<<i<<"] = "<<envp[i];
return 0;
} Biên dịch:

g++ 1.cpp Thực thi:

./a.out 1 2 3 4 5 6 "abc" "def" "varn" "varn+1" "..." [mp@localhost ~]$
./a.out 1 2 3 4 5 6 "abc" "def" "varn" "varn+1" "..." Kết quả:



argc = 12
argv[0] = ./a.out
argv[1] = 1
argv[2] = 2
argv[3] = 3
argv[4] = 4
argv[5] = 5
argv[6] = 6
argv[7] = abc
argv[8] = def
argv[9] = varn
argv[10] = varn+1
argv[11] = ...
Envirenment variables :
envp[0] = ORBIT_SOCKETDIR=/tmp/orbit-mp
envp[1] = HOSTNAME=localhost.localdomain
envp[2] = IMSETTINGS_INTEGRATE_DESKTOP=yes
envp[3] = TERM=xterm
envp[4] = SHELL=/bin/bash
envp[5] = DESKTOP_STARTUP_ID=
envp[6] = XDG_SESSION_COOKIE=63c0e623426e1eb3c0e0462d0000000 c-1283367080.880570-2076814743
envp[7] = HISTSIZE=1000
envp[8] = GTK_RC_FILES=/etc/gtk/gtkrc:/home/mp/.gtkrc-1.2-gnome2
envp[9] = WINDOWID=41943183
envp[10] = GNOME_KEYRING_CONTROL=/tmp/keyring-Sh02yZ
envp[11] = IMSETTINGS_MODULE=SCIM
envp[12] = USER=mp
envp[13] = LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so =01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;0 1:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30; 42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01 ;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01; 31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:* .Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01; 31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31 :*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*. rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7 z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif= 01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01 ;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;3 5:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;3 5:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35: *.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:* .mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*. qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm= 01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=0 1;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35 :*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:* .axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.a ac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.mid i=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg= 01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01; 36:*.spx=01;36:*.xspf=01;36:
envp[14] = SSH_AUTH_SOCK=/tmp/keyring-Sh02yZ/ssh
envp[15] = SESSION_MANAGER=local/unix:@/tmp/.ICE-unix/1727,unix/unix:/tmp/.ICE-unix/1727
envp[16] = USERNAME=mp
envp[17] = DESKTOP_SESSION=gnome
envp[18] = MAIL=/var/spool/mail/mp
envp[19] = PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/mp/bin
envp[20] = QT_IM_MODULE=xim
envp[21] = PWD=/home/mp
envp[22] = XMODIFIERS=@im=SCIM
envp[23] = GDM_KEYBOARD_LAYOUT=us
envp[24] = LANG=en_US.utf8
envp[25] = GNOME_KEYRING_PID=1720
envp[26] = GDM_LANG=en_US.utf8
envp[27] = GDMSESSION=gnome
envp[28] = SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
envp[29] = HISTCONTROL=ignoredups
envp[30] = HOME=/home/mp
envp[31] = SHLVL=2
envp[32] = GNOME_DESKTOP_SESSION_ID=this-is-deprecated
envp[33] = LOGNAME=mp
envp[34] = DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-p2Glb1F8UV,guid=37a94c72b2c254f646a8ec4200000019
envp[35] = LESSOPEN=|/usr/bin/lesspipe.sh %s
envp[36] = WINDOWPATH=1
envp[37] = DISPLAY=:0.0
envp[38] = G_BROKEN_FILENAMES=1
envp[39] = XAUTHORITY=/var/run/gdm/auth-for-mp-2rJaMK/database
envp[40] = COLORTERM=Terminal
envp[41] = _=./a.out

Thank to admin from:  http://www.vndf.net/archive/index.php/t-7752.html
Khoquachoqua :D 

Thứ Sáu, 28 tháng 6, 2013

Các thao tác dừng GDB

trong console của GDB, để thực thi các lệnh của linux

(gdb) shell [lenh_linux]

ví dụ:
(gdb) shell clear
(gdb) shell ls

------------------------------------------
để set break point ở một vị trí nào đó:

(gdb) break [so_dong]
hoặc
(gdb) break [ten_ham]
ví dụ:
cần đặt breakpoint tại dòng thứ 10 trong main.c
(gdb) break 10

hoặc đặt breakpoint tại hàm main
(gdb) break main

------------------------------------------
để xóa breakpoint
(gdb) delete [so_thu_tu_break_point]

ví dụ
xóa breakpoint thứ 2
(gdb) delete 2

------------------------------------------
sau khi đã đặt breakpoint( hoặc ko cần đặt breakpoint tùy cách chúng ta debug), thì chúng ta bắt đầu chạy chương trình bằng lệnh sau
(gdb) run

------------------------------------------
muốn xem chương trình đã dừng ở đâu
(gdb) list

ở ví dụ của chúng ta chỉ có hàm main, do đó khi dùng lệnh list thì sẽ hiển thị duy nhất các dòng code của hàm main. Còn nếu chương trình đang chạy ở 1 function nào đó, ví dụ function aaaa thì sẽ list code của function đó.

------------------------------------------
chúng ta muốn chương trình chạy dòng lệnh kế tiếp thì trong gdb gõ
(gdb) next [so_dong]

nếu không có [so_dong ] thì dòng lệnh kế tiếp dòng lệnh hiện tại được thực thi, còn nếu có [so_dong] thì chương trình sẽ thực thi từ dòng lệnh hiện tại tới dòng lệnh [so_dong]

------------------------------------------
muốn chạy vào bên trong thân hàm
(gdb) step

------------------------------------------
muốn quay lại đầu hàm thì dùng lệnh
(gdb) return

------------------------------------------
muốn chương trình thực thi tiếp cho đến breakpoint kế hoặc đếnt hết chương trình
(gdb) continue

------------------------------------------
trong quá trình chạy debug chúng ta muốn xem một biến có giá trị bằng bao nhiêu
(gdb) display [ten_bien]

ví dụ: trong hàm main của chúng ta có biến date, mà muốn xem biến này chúng ta thực hiện lệnh
(gdb) display date

------------------------------------------
muốn in giá trị của 1 biến trong console
(gdb) print [ten_bien]

ví dụ
(gdb) print date

------------------------------------------
muốn in địa chỉ của biến
(gdb) print &[ten_bien]

ví dụ
(gdb) print &date

------------------------------------------
hiển thị kiểu dữ liệu của biến
(gdb) ptype [ten_bien]
hoặc
(gdb) whatis [ten_bien]

ví dụ
(gdb) ptype date

------------------------------------------
gán giá trị cho 1 biến
(gdb) set variable [ten_bien] = [value]
(gdb) continue

ví dụ:
(gdb) set variable date = 15
(gdb) continue

------------------------------------------
compile lại file thực thi
(gdb) make

Nguồn : http://mathhoang.blogspot.com/2010/12/huong-dan-debug-chuong-trinh-voi-gdb.html
Cái này không thể thiếu nhé :D

Chủ Nhật, 9 tháng 6, 2013

AT&T vs INTEL

AT&T vs INTEL

Đây là 2 cú pháp của ngôn ngữ Assembly.Nó sẽ gây nhầm lẫn cho người học Intel rồi chuyền qua AT&T và ngược lại . Nói dài dòng vậy đủ rồi let 's begin:

Prefixes : theo mình hiểu là cái gắn vào đầu 1 ký tự nào đó làm nó có 1 chút thay đổi nhỏ
Trong AT&T thì "%" sẽ được gắn vào đầu các thanh ghi và "$" gắn vào đầu các cái hằng số được gán vào
Trong Intel dùng hex và binary thì sẽ được gắn "h" và "b" ở phía sau hằng số.
VD:
Intel                                                                    AT&T
mov eax,1                                               movl $1,%eax
mov ebx,0ffh                                          movl $0xff,%ebx
int 80h                                                    int $0x80

Direction of operands: dẫn đến các phép toán (dịch  hơi chuối vì mình ko pro mấy én lịt) ><
Nói chung chỗ này thì thể hiện rõ AT&T nó ngược với Intel làm mình nhiều khi hơi điên chỗ này ><
Intel syntax : tham số đầu là destination hay còn là đích , tham số sau là source tham số nguồn
AT&T syntax: tham số đầu là Source nguồn gốc tội lỗi , tham số sau là Destination đích
VD:
Intel                                                                  AT&T
instr dest,source                                      instr source,dest
mov eax,[ecx]                                         movl (%ecx),eax
Chúng ta thấy ở vd hàng 2 bên intel [] còn bên AT&T () ???? kỳ hén

Memory Operands: Tính toán trên memory j đó dịch thế  cũng được :D
Intel thì ta cũng đã thấy để lấy địa chỉ của thanh ghi thì thanh ghi sẽ được bao bọc bỏi []
AT&T thì được ()
VD
Intel                                                             AT&T 
mov     eax,ebx                movl  (%ebx),%eax
mov     eax,[ebx+3]         movl 3(%ebx),%eax 

Qua vd trên ta thấy cấu truc của AT&T nó được che khuất hay ẩn hơn so với Intel
Sự khác nhau này làm mình cũng thấy khó khăn do ko quen lắm :(
nó ko viết rõ ràng cho mình hỉu :(
Intel                                                         AT&T
segreg:[base+index*scale+disp]                     %segreg:disp(base,index,scale)

À quên khi dùng trong kiểu này thì các hằng số mình ko thêm "$" khi trong () của AT&T nhé
VD
Intel                                                                                     AT&T
instr   foo,segreg:[base+index*scale+disp]           instr   %segreg:disp(base,index,scale),foo
mov eax,[ebx+20h]                                              movl 0x20(%ebx),eax
add eax,[ebx+ecx*2h]                                          movl  (%ebx,%ecx,0x2),%eax
lea  eax,[ebx+ecx]                                                leal  (%ebx.%ecx),%eax
sub eax,[ebx+ecx*4h-20h]                                   subl  -0x20(%ebx,%ecx,0x4),%eax

Phần cuối là suffixes : hay còn gọi là phần gắn vào đuôi mấy cái chữ cái làm đổi nghĩa của nó đồ ó
Có thể thấy AT&T nó gợi nhớ cú pháp sau các opcode và nó còn tùy thuộc vào kích thước toán hạng
AT&T
'l' is long
w is word
b is byte
Đương nhiên Intel cũng thể hiện nhưng nó ghi ở các memory operands như byte word dword .....
VD
Intel                                                                          AT&T
mov  al.bl                                                       movb  %bl.%al
mov  ax,bx                                                     movw  %bx,%ax
mov eax,ebx                                                   movl   %ebx,%eax
mov eax,dword ptr [ebx]                                movl  (%ebx),%eax
Tới đây hết dồi... Lần đầu viết bài nên có nhiều sai sót có j đừng ném gạch em nhé  :D

Thank to http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm đã cho ta tài liệu này :D
và tôi ko quên http://translate.google.com đã giúp tui dịch :D
KHOQUACHOQUA nhé