Trang 1 / 10 12346 ... LastLast
Hiển thị kết quả từ 1 đến 10 / 100

Chủ đề: Con trỏ C++

  1. #1
    Tham gia
    12-04-2007
    Location
    Việt Nam Quê Hương tui
    Bài viết
    241
    Like
    0
    Thanked 0 Times in 0 Posts

    Thông tin Con trỏ C++

    Cho mình hỏi là trong C++ hình như tồn tại 2 loại con trỏ nhưng mình không biết là cách sử dụng chúng như thế nào? Nghe một số người nói thì có những bài sử dụng con trỏ sẽ giải quyết vần đề nhanh gọn hơn so với những cách dùng biến khác (cái này mình ko rõ nha vì chỉ nghe nói thôi). Ai có kinh nghiệm nhìu khi sử dụng con trỏ thì cho mình xin ý kiến nha. Thanks.
    Quote Quote

  2. #2
    Tham gia
    02-02-2005
    Bài viết
    219
    Like
    0
    Thanked 3 Times in 3 Posts
    Có ty tỷ loại con trỏ. Ai bảo bạn 2 là bậy. Cứ đọc sách đi rồi ra Constructor với Destructor.

  3. #3
    Tham gia
    12-04-2007
    Location
    Việt Nam Quê Hương tui
    Bài viết
    241
    Like
    0
    Thanked 0 Times in 0 Posts
    Oh, sorry đã làm anh hỉu lầm. Ý của em là 2 cách khai báo con trỏ. Tức là kieu *tencontro; và kieu ^tencontro.
    Va` hien em dang kiem ba`i tap cho thấy khi su dung con tro cua C++ se giai quyet bai toan mot cach nhanh gon (it phép toán) trong khi sử dụng những cái khác thì bài toán trở nên phức tạp và khó hỉu. Nhưng chủ yếu la` loại con trỏ * thôi, chứ loại kia em chưa học chỉ làm những bài đơn giản, chứ mấy bài phức tạp thì em cũng chịu. Thanks

  4. #4
    Tham gia
    12-02-2007
    Location
    HCM - NT
    Bài viết
    218
    Like
    0
    Thanked 1 Time in 1 Post
    Cám ơn Mokona đã gợi ý để mình post bài viết này. Có lẽ bạn đang làm 1 project về Object và muốn so sánh ở tính năng Object của C++ với hỗ trợ con trỏ cùng với các ngôn ngữ khác phải không?

    Mình cũng đã viết bài viết này lâu rồi (trong 1 đồ án nhỏ về phát triển HDH của môn học HDH) và nhiều lần định post lên giới thiệu với mọi người. Nhưng do vụ “xì căng đan” trong topic “C++ vs tất cả các ngôn ngữ lập trình” cách đây gần 1 tháng vì mọi người cho rằng mình quá “lăng xê” C++ nên lại thôi… Nhưng mình thật sự rất muốn giới thiệu điểm mạnh C++ bởi tính năng con trỏ đến các bạn.
    Hy vọng lần này sẽ không tái diễn như trước nữa vì mình chả lấy C++ vs với ngôn ngữ nào nữa trong Topic này, nếu có thì cũng chỉ so đơn giản với một số ngôn ngữ để dễ hình dung mà thôi. Do đó mình mong có sự ủng hộ của các bạn một chút để mình có thê tự tin “spam” kiến thức một chút trong những Topic lần sau. Xin cám ơn các bạn


    Quay lại về Topic.
    Mình xin nói lại là C++ chuẩn có loại 2 con trỏ.
    Nhưng tại thời điểm này (2007), lý ra C++ đã có tới 3 loại con trỏ (con trỏ point *, con trỏ far point, và con trỏ handle^). nhưng far point đã hủy bỏ rồi trên môi trường Windows rồi. Còn con trỏ Handle mới chính thức được các nhà khoa học đưa vào ngôn ngữ C++ vào tháng 11/2005 để C++ tăng khả năng hoạt động trên môi trường .NET và chỉ có thể sử dụng con trỏ này trong VS2005 và ngôn ngữ C++ này gọi là C++/CLI (Common Language Infrastructure).

    Con trỏ C++ có thể làm thay đổi cả một hệ thống:
    Có ý kiến cho rằng “con trỏ của C/C++ có thể thay đổi cả một hệ thống” Lần trước có 1 bạn bảo có ai thử phân tích câu nói này xem nhưng tôi không có dịp trả lời. Và tại sao 2 hệ điều hành lớn hiện nay là Windows và Linux được phát triển bằng C/C++ mà không phải là một ngôn ngữ khác như PASCAL hay ASM?
    Tôi cũng cố gắng trả lời 2 câu hỏi này luôn trong nó luốn trong TOPIC.

    + Vấn đề bắt đầu là con trỏ của C/C++

    C++ for DOS có 1 con trỏ có thể làm thay đổi hệ thống chính là far point (32bit). Đó mới đúng là linh hồn của C/C++:
    Code:
    void far* pMem;
    void *pMem;
    2 con trỏ này khác nhau chỗ nào? Để giải thích được nó có lẽ mình phải phân tích thêm về cách tổ chức MEMMORY của PC và tổ chức Data trên RAM của hệ điều hành MS DOS cũng như WINDOWS ngày nay.

    I. CÁC BỘ NHỚ TRÊN MÁY TÍNH

    Trước tiên là quy định về đơn vị bộ nhớ:
    Code:
    1 byte = 8 bits
    1 word = 2 bytes
    1 double word = 4 bytes
    1 quad word = 8 bytes
    1 octal word = 8 bytes
    1 paragraph = 16 bytes
    1 kilobyte (KB) = 1,024 bytes
    1 megabyte (MB) = 1,024KB = 1,048,576 bytes
    1 gigabyte (GB) = 1,024MB = 1,073,741,824 bytes
    1 terabyte (TB) = 1,024GB = 1,099,511,627,776 bytes
    1 petabyte (PB) = 1,024TB = 1,125,899,906,842,624 bytes
    Cái này mình chỉ nhắc lại thôi chứ cũng chả có gì khó hiểu.

    Bộ nhớ chính mà CPU có thể truy xuất trên PC 5 loại đó là:
    1. Registers
    2. Cache
    3. RAM
    4. ROM (ở đây mình không xét tới ROM vì nó chỉ đọc chứ không ghi được)
    5. Disk storage



    * Registers là các thanh ghi nằm ngay bên trong CPU. Và nó là nơi mà CPU có thể truy xuất nhanh nhất.

    CPU32 bit (thế hệ Pentium ngày nay) bao gồm các thanh ghi:
    - Nhóm 16 bit.
    + AX, BX, BX, DX: Chức năng chính của nhóm thanh ghi này thực hiện các chức năng là tính toán như dịch trái, dịch phải, cộng trừ nhân chia, nhớ trong quá trình tính toán...
    Trong mỗi thanh ghi như vậy lại chia ra 2 thanh ghi con để phục vụ tính toán. Ví dụ AX gồm có AH và AL. AH (8bit cao high trong AX) và AL (8 bit thấp Low trong AX)
    + CS, DS, ES, FS, GS, SS: Nhóm thanh ghi này chính là cha đẻ của con trỏ trong ngôn ngữ C/C++. Tác dụng chính của nó là quản lý bộ nhớ ở vùng thấp LOWMEMORY.
    + CS: Chứa địa chỉ bắt đầu của code trong chương trình.
    + DS: Chứa địa chỉ của các biến khai báo trong chương trình.
    + SS: Chứa địa chỉ của bộ nhớ Stack dùng trong chương trình.
    + ES: Chứa địa chỉ cơ sở bổ sung cho các biến bộ nhớ (Heap).
    -> StackHeap là gì tôi sẽ phân tích sau.

    - Nhóm 32 bit.
    + EAX, EBX, ECX, EDX,...: Giống AX,BX,CX,DX nhưng có độ rộng là 32 bit để phục vụ quá trình tính toán.


    - Nhóm 48 bit, 16bit (quản lý Memory).
    Những tài liệu tiếng việt rất ít nhắc tới những nhóm thanh ghi trong CPU này trong khi nó rất quan trọng. Có lẽ là vì nó chỉ có ở những CPU 8088 trở về sau cho đến Pentium mà thôi mà thôi.
    + GDTR (48bit), LDTR (48bit): là những thanh ghi chuyên quản lý HighMemory.
    + IDTR (16bit), TR (16bit): Nhóm 2 thanh ghi này chuyên quản lý ngắt (interrupts) và phân luồng xử lý (multitasking).

    Và cuối cùng là các thanh ghi cờ (FLAGS) và một số thanh ghi điều khiển (CONTROL)

    * Cache:
    Bao gồm 2 loại Cache. Level 1 (L1) và Level 2 (L2).
    - L1 nằm ngay trong CPU. CPU sử dụng nó để lưu trữ một số thông tin trong quá trình xử lý và L1 càng lớn thì cũng đồng nghĩa là “tốc độ xử lý sẽ nhanh”. Đó là lý do 1 con CPU Pentium IV và 1 con CPU Celeron cùng 1 tốc độ nhưng P4 đắt hơn rất nhiều là đo L1 lớn. CPU 2 Core sẽ có cách L1x2.
    - Khi L1 đầy thì CPU sẽ sử dụng tiếp L2. L2 nằm ngay trên Mainboard do đó tốc độ truy xuất L2 sẽ chậm hơn L1.

    * RAM
    - Là bộ nhớ chính của CPU và tốc độ truy xuất RAM (Level 3) chậm hơn L2. Bởi vì RAM cấu tạo chính là các tụ điện vô cùng nhỏ xếp liên tiếp nhau đại diện cho từng bit dữ liệu. Khi tụ được nạp điện có nghĩa là trạng thái 1 và ngược lại. Vì là tụ điện nên nó sẽ xả mất điện trong khoảng thời gian t giây. Do vậy nó cần 1 khoảng thời gian làm tươi (refesh rate) để nạp điện lại và do đó CPU phải chờ đợi mới mà không thể truy xuất tức ngay lập tức được. Do đó máy tính muốn chạy ổn định trên 2 thanh RAM khác nhau thì buộc 2 thanh RAM này phải cùng 1 tầng số làm tươi.

    * Disk Drive
    - RAM đầy! một điều luôn xảy ra khi chạy các ứng dụng lớn. Hệ điều hành sẽ giả lập HARDDISK để làm RAM. Và khái niệm này là Virtual RAM. Tốc độ truy xuất trên HDD rất chậm bởi vì khi truy xuất nó có một sự di chuyển của cơ học.

    II. TỔ CHỨC DỮ LIỆU TRÊN RAM

    Khi xét về con trỏ chúng ta chỉ xét tới RAM. Bởi vì con trỏ của C/C++ chỉ có tác dụng trên RAM chứ không thể nào truy xuất vào L1 và L2 được.
    Mỗi BYTE (8bit) trên RAM sẽ được đánh địa chỉ từ thấp lên cao.



    Các ngôn ngữ khác chỉ có thể biểu diễn giá trị thực của BYTE trên RAM. Còn riêng với C/C++ thì có thể biễu diễn địa chỉ của của chính BYTE đó và nó chính là biến con trỏ.
    Ví dụ:
    Code:
    typedef struct unsigned char BYTE;
    BYTE far* a = 0x2; // Địa chỉ 2 trên hình
    
    cout << (BYTE)*a; 
    // Nếu RAM hiện tại giống trên hình thì sẽ in ra giá trị 93
    // vì 1011101b = 5Dh = 93d
    Như vậy con trỏ far chính là con trỏ chính xác trên RAM. Và muốn truy xuất được dữ liệu trên RAM với địa chỉ xác định thì chỉ có một cách là dùng con trỏ far.
    Vậy con trỏ bình thường như BYTE *a khác con trỏ BYTE far* a; như thế nào?

    Hiện nay, các CPU có 2 kỹ thuật chính để quản lý bộ nhớ là segmentation paging .

    Segmentation: Là cách chia Memory thành nhiều đoạn (segments) liên tục. và Mỗi chương trình khi chạy sẽ được cấp phát 1 hoặc nhiều đoạn Segments. Nhờ vậy mà mỗi chương chình độc lập về bộ nhớ lẫn nhau, nó không thể can thiệp vào vùng nhớ của chương trình khác bằng con trỏ. Lưu ý một điều là không phải lúc nào 1 ứng dụng cũng chỉ là 1 Segment. Một ứng dụng lớn sử dụng nhiều tài nguyên có thể chiếm tới rất nhiều Segments.


    - Nếu đứng từ dười lên cao. LowMemory (là 1 MB đầu tiên của RAM) dành riêng để nạp các file Hệ điều hành và CPU truy xuất phần này một cách trực tiếp qua hệ thống BUS không cần các thiết bị điều khiển (nhanh hơn phần khác trên RAM).
    - Phần HighMemory chính là phần của ứng dụng. Nó chia ra từng đoạn như vậy. Trong từng Page bao gồm code của chương trình và một khoảng data cho chúng ta khai báo biến.

    Ở HDH MSDOS thì phần data này chỉ có 64KB. Do đó nên khai báo một cái mảng double aMang[1000000]; chắc chắn sẽ không bao giờ được. Với Windows thì 4MB nên chúng ta được tự do hơn 1 xíu. Và con trỏ * bình thường mà chúng ta hay dùng chỉ quản lý dữ liệu ở phần Data của chương trình chúng ta mà thôi. Có lẽ tới đây các bạn đã hình dung được sự khác nhau của far point và point.

    Paging: Là cách mà CPU giả lập những Segments thành những Page trên HDD, dĩ nhiên nó chỉ sử dụng phương pháp này khi RAM đã đầy. Và tốc độ máy tính lúc này sẽ rất chậm bởi khả năng truy xuất dữ liệu HDD chậm hơn RAM rất nhiều lần.



    * Chúng ta sẽ nhìn cây RAM một cách chính xác hơn dưới HDH của MS.

    Đây là mô hình tổ chức Memory của MSDOS và WINDOWS (LINUX cũng tương tự nhưng khác đi một chút vì kernel của Linux chắn chắn phải khác Windows rồi).



    Tôi xin nói lại là RAM chia ra làm 2 vùng rõ ràng. LowMemory (từ 0 -> 0x9FFFF) và HighMemory (từ 0x9FFFF đến hết RAM -> phần Extended);
    Tại sao phải chia làm 2 phần như vậy:
    - Phần LowMemory là phần mà CPU có thể truy xuất trực tiếp tới RAM bằng hệ thống BUS của mình. Có lẽ sẽ dể hiểu hơn với cái hình này. Số lượng Address Lines chính là số bit của CPU. Ví dụ CPU16bit (hàm này hiếm rồi) thì sẽ có 16 đường BUS. Nó sẽ truy xuất RAM bằng cách nhảy mỗi step là 16bit (64kb/1 lần truy xuất) và chúng ta có thể tính được số lần truy để CPU có thể truy xuất tới 1 địa chỉ nào đó trên RAM ở phần LowMemory. Tương tự với CPU32.



    - Phần HighMemory là phần mà CPU muốn truy xuất được phải thông BUS hệ thống. Do đó phải cài 1 XMS DRIVER. Với MS DOS thì có tên là EMM386.EXE và HIMEM.SYS (2 chương trình quá quen thuộc với những ai hay đi cài đặt máy tính) .

    1. Khảo sát LowMemory

    + Trong 1KB đầu tiên của RAM (0x0 – 0x3FF) đó chính là bảng VECTOR ngắt mềm của MSDOS dùng để điều khiển phần cứng. Mỗi ngắt có nhiệm vụ riêng như ngắt màn hình, ngắt phím… các vector ngắt này rất nhiều tôi cũng không rành lắm, nếu bạn nào thích SYSTEM PROGRAMING hoặc lập trình ASM thì quá rành. Bảng Vector Ngắt này viết rất rõ trong cuốn Guild Techhelp của hãng NORTON, mình thấy gần như là đầy đủ.

    + 256 byte tiếp theo (0x400 – 0x4FF) Chứ thông tin bảng VECTOR ngắt cứng và địa chỉ PORT của cổng COM, PRINT…

    + 0x500 – 0xFFFF (64KB) là phần để nạp chương trình HDH MSDOS và để CPU thi hành nó. Khi MS DOS khởi động thì 3 tập tin được nạp lên phần này chính là IO.SYS, MSDOS.SYS, COMMAND.COM, và số dung lượng trống còn rất ít (489K). Do vậy nếu không cài XMS DRIVER thì không thể nào chạy được các ứng dụng lớn.
    Thông tin khi mình DEBUG (Trên HDH WINDOWS) phần Conventional Memory (LowMemory). Bạn có thểm xem bằng lệnh mem. Chỉ ưu tiên nạp các ứng dụng HĐH, trong đó MS DOS chiếm gần hết rồi.
    Code:
    E:\DOCUME~1\EXECUT~1>mem /PROGRAM
      Address     Name          Size       Type
      -------     --------     ------     ------
      000000                   000400     Interrupt Vector
      000400                   000100     ROM Communication Area
      000500                   000200     DOS Communication Area
      000700      IO           000370     System Data
      000A70      MSDOS        001670     System Data
      0020E0      IO           0020C0     System Data
                  KBD          000CE0      System Program
                  HIMEM        0004E0      DEVICE=
                               000490      FILES=
                               000090      FCBS=
                               0001B0      LASTDRIVE=
                               0007D0      STACKS=
      0041B0      COMMAND      000A20     Program
      004BE0      MSDOS        000070     -- Free --
      004C60      COMMAND      0005A0     Environment
      005210      MEM          0004E0     Environment
      005700      MEM          0174E0     Program
      01CBF0      MSDOS        0833F0     -- Free --
      09FFF0      SYSTEM       02B000     System Program
      0CB000      IO           003100     System Data
                  MOUSE        0030F0      System Program
      0CE110      MSDOS        0004D0     -- Free --
      0CE5F0      MSCDEXNT     0001D0     Program
      0CE7D0      REDIR        000A70     Program
      0CF250      DOSX         0087A0     Program
      0D7A00      DOSX         000080     Data
      0D7A90      MSDOS        018560     -- Free --
    
        655360 bytes total conventional memory
        655360 bytes available to MS-DOS
        633056 largest executable program size
    
       1048576 bytes total contiguous extended memory
             0 bytes available contiguous extended memory
        941056 bytes available XMS memory
               MS-DOS resident in High Memory Area
    
    E:\DOCUME~1\EXECUT~1>
    Ví dụ như ứng với với 1024KB đầu tiên trên RAM. Chúng ta biết rằng bộ nhớ của màn hình nằm từ vị trí B800:0000 đến B800:0F9F. Như vậy chúng ta hoàn toàn có thể giả lập lệnh clrscr() bằng cách set zeromemory khoảng bộ nhớ này hay printf(). Hoặc lập trình thành một đối tượng chuyên dụng hơn như cout của C++.
    1 đoạn CODE lấy ký tự tại tọa độ y, x của của sổ console như sau (Lập trình trên BORLAND C++):
    Code:
    struct cell{
    	char chr;
    	char color;
    };
    cell far* scr = (cell far* )MK_FP(0xB800, 0);
    cell chr = scr [(y-1)*80 + x-1];
    
    -> chr.chr: byte chứa mã ASCII của ký tự tại tọa độ dòng y, cột x
    
    -> chr .color: byte chứa màu của ký tự và màu nền tại tọa độ dòng y, cột x
    Bạn nào đã từng lập trình hệ thống thì chắc có thể biết điều này.

    Tôi cũng xem một số code của PASCAL. Nó có thể làm được điều này nhưng dưới dạng ngôn ngữ ASM bằng cách gọi ngắt nhưng như vậy thì cũng chẳng còn gì hay.

    2. Khảo sát phần HighMemory
    Đây là cái nhìn tổng quát hơn về tổ chức RAM. Phần Protected Mode chính là HighMemory. Các chương trình lớn đều được nạp và chạy ở trên phần này.



    Và trong vùng Application thì lại được tổ chức bộ nhớ của như sau:



    Bao gồm:
    - CODE: của chương trình dưới dạng mã máy.
    - DATA: Biến toàn cục được khai báo trong chương trình của chúng ta.
    - HEAP: lưu trữ bộ nhớ do chương trình cấp phát.
    Ví dụ như khi ta khai báo:
    int *i = new int[100];
    Thì CPU sẽ tìm một khoảng trống trên HEAP có dung lượng 100*sizeof(int) = 200byte. i mang địa chỉ đầu tiên của vùng nhớ này và biến con trỏ i được đưa vào STACK. Do đó vùng nhớ trên HEAP sẽ tồn tại cho đến khi chúng ta gọi delete i.
    - STACK: Lưu trữ các biến tạm như trong hàm. Khi kết thúc hàm thì nó sẽ tự động giải phóng.
    Được sửa bởi eXecutive lúc 15:33 ngày 06-10-2007

  5. #5
    Tham gia
    12-02-2007
    Location
    HCM - NT
    Bài viết
    218
    Like
    0
    Thanked 1 Time in 1 Post
    III. C++ BIỂU DIỄN CON TRỎ NHƯ THẾ NÀO?
    Địa chỉ trên RAM được biểu diễn dưới 2 dạng.
    - Địa chỉ vật lý: Biểu diễn chính xác địa chỉ trên RAM. Ví dụ từ 0 – 1MB đầu trên RAM thì sẽ biểu diễn bằng 0x0 - 0xFFFFF.
    - Địa chỉ logic: Sử dụng 16 Bit Segment và 16bit Offset để biểu diễn địa chỉ.
    Ví dụ: Các địa sau là địa chỉ Logic: 0000:0021, 0000:0011, 0000:0001
    + Cách chuyển từ địa chỉ logic sang địa chỉ vật lý:
    (segment : offset -> đc_vật_lý)
    đc vật lý = segment * 10h + offset

    + Cách chuyển từ địa chỉ vật lý sang địa chỉ logic:
    (đc_vật_lý -> segment : offset)
    segment = đc vật_lý / 10h
    offset = đc vật_lý % 10h

    10h = 16d nha các bạn. Tức là nếu sử dụng hệ HEX (thập lục phân) thì nhân hay chia cho 10. Còn sử dụng hệ DEG (thập phân) thì chia cho 16.

    Cách biểu diễn địa chỉ RAM ở phần LOWMEMORY khác hẳn với phần HIGHMEMORY.
    1. Biểu diễn địa chỉ ở phần LOW MEMORY:



    CPU sẽ sử dụng 2 thanh ghi:
    - DS (DS “Data Segments” -> “quản lý biến trong DATA chương trình”) làm SEGMENT.
    - AX là OFFSET.
    Do đó địa chỉ biểu diễn phần LOWMEMORY sẽ là: DS:AX
    => far * là chỉ một cách nhìn trong suốt với DS:AX Cũng như giữa C++ và ASM.

    Tương tự cho các cặp khác như CS:AX, SS:AX, ES:AX

    2. Biểu diễn địa chỉ ở phần HIGH MEMORY:
    -> Con trỏ far* rất dễ hiểu nhưng con trỏ point mà chúng ta hay dùng khác. Bởi lẽ nó quản lý ở vùng nhớ High.
    - Vấn đề ở đây là một cây RAM có dung lượng lớn. (>4MB đã là lớn lắm với CPU rồi). Nếu CPU dùng thanh ghi DS để biểu diễn thì chỉ có thể biểu diễn được: FFFFh (16bit) x 10h = FFFF0 (byte) bằng 1MB. Do đó Không có cách nào để biểu diễn được địa chỉ cây ram lớn hơn 1MB bằng chính giá trị Segments của thanh ghi DS được!
    - Để giải quyết vấn đề này người ta phải sử dụng những thanh ghi 32 bit, 48bit và cần có sự can thiệp của Hệ Điều Hành (chính là các XMS Driver như EMM386.EXE, HIGHMEM.SYS). Chúng ta xem hình dưới đây.



    Con trỏ * sử dụng 2 thanh ghi là DS và EAX để biểu diễn địa chỉ bộ nhớ. Nhưng cách thức khác hoàn toàn.

    - Biểu diễn OFFSET sử dụng tới 32 bit. Thanh ghi đảm nhiệm việc này chính là EAX.
    - DS: Ở đây được sử dụng không còn mang giá trị là Segment như trên nữa mà là một “Segment Selector”. Segment Selector chỉ đến Index của bảng Descriptor Table.
    16 bit của thanh ghi DS (Ở đây gọi là Segment Selector) tổ chức như sau:



    -> 12 bit phía trước đánh dấu địa chỉ cần tra thuộc chỉ mục Index thứ mấy trong bảng Descriptor Table (có thể là bảng GDT hoặc LDT) (12 bit thì có tối đa 4095 chỉ mục).
    -> Thành phần quan trọng nhất là bit ở vị trí thứ 3: gồm 2 bit trạng thái. Bit 0 là GDT và 1 là LDT.
    + Global Descriptor Table (GDT): Mỗi hệ điều hành chỉ có duy nhất 1 bảng GDT.
    + Local Descriptor Table (LDT): Nhưng có thể có nhiều LDT. Mỗi bảng LDT quản lý một tiến trình đang chạy cụ thể.

    Vấn đề là địa chỉ bắt đầu của bảng Descriptor Table lưu ở đâu? Để biết địa chỉ GDT hay LDT ở đâu trên RAM thì 2 thanh ghi GDTR và LDTR nằm trong CPU sẽ lưu trữ thông tin đó.
    Địa chỉ của bảng GDT được lưu trong thanh ghi 48bit GDTR
    Địa chỉ của bảng LDT được lưu trong thanh ghi 48bit LDTR



    Cấu trúc thanh ghi GDTR gôm 32 bit đầu tiên là Base Address chính là địa chỉ bắt đầu của GDT. 16 bit còn lại là sizeof(GDT).

    Việc cuối cùng chỉ là tra Address trên Descriptor Table với chỉ số Index đã có. Kết quả trả về là 1 con số 32 bit. Với 32 bit thì con số này có thể biểu diễn được dung lượng tới 4GB RAM.

    Dưới đây là một mô hình tổng quát hơn.



    Mở rộng hơn một xíu nữa thì đây là tổng thể cách tổ chứ toàn bộ của phần High Memory.



    Nó có một cấu trúc như là “danh sách liên kết”. Địa chỉ của NODE đầu tiên Page Directory sẽ được lưu trong thanh ghi điều khiển CR3 và cứ tiếp tiếp… như thế.

    => Khi chúng ta khai báo và sử dụng con trỏ *. Đó là hàng loạt các xử lý bên trong CPU có lẽ 1 programer chẳng cần quan tâm đến điều đó nhưng lý thuyết về con trỏ của C/C++ thì trừu tượng vô cùng.

    V. CON TRỎ FAR ĐÃ BỊ DIE TRÊN WINDOWS

    MS đã hủy bỏ con trỏ far của C/C++ nếu lập trình C++ trên môi trường Windows. Cũng đơn giản là vì Windows không muốn có một chương trình nào khác can thiệp vào hệ thống của mình ngoài Windows.

    Do đó nên việc các ngôn ngữ như Java, C#, VB, VB.NET… không có con trỏ mà thay vào đó là tham chiếu cũng hết sức bình thường. Bởi lẽ sức mạnh của C++ đã bị mất đi khá nhiều trên môi trường Windows rồi.

    Tuy vậy, MS lại nhẹ nhàng đưa vào một biến đại diện an toàn để thay thế con trỏ là HANLDE. Do đó chúng ta muốn gửi thông tin 1 chương trình khác, đơn giản chúng ta chỉ cần tìm HANDLE của nó và SendMessage với tham số thứ nhất là HANDLE cần đưa vào.

    Ví dụ đây là mã nguồn của hàm malloc và toán tử new thực hiện dưới con trỏ HANDLE.

    Code:
    #include<windows.h>
    #include<stdio.h>
    
    void main(){
          HANDLE hHeap;
          unsigned char *buffer;
    
    // Lấy địa chỉ HEAP của chtr mình dưới dạng HANDLE
          hHeap = GetProcessHeap();	
    // Muốn lấy HEAP của chtr khác thì sử dụng GetProcessHeaps()
          if(hHeap==NULL){
                printf("No heap!\n"); exit(1); }
    
    // Cấp phát 1024 byte. Và set giá trị mỗi BYTE là 0. 
    // -> Buffer nắm giữ giá trị đó.
    
                buffer = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,1024);             
                if(buffer==NULL){ 
                      printf("No heap space!\n"); exit(1);}
                      printf("buffer[511]=%X, buffer has been
                            zeroed\n",buffer[511]);
                      buffer[512]=0xCA;
                      printf("buffer[512]=%X\n",buffer[512]);
                if(HeapFree(hHeap,HEAP_NO_SERIALIZE,buffer)){
                      printf("have returned memory to the collective\n");
                }
          return;
    }

    Tài liệu tham khảo:
    Memory Management Algorithms and Implementation in C/C++


    VI. XÂY DỰNG MỘT HỆ ĐIỀU HÀNH BẮT ĐẦU TỪ ĐÂU?

    Một HDH cấp thấp như MS DOS hay UNIX chắc chắn phải viết bằng ASM. Khi đã có HDH thì ngôn ngữ lập trình mới tồn tại.
    Windows muốn khởi động thì phải khởi động MSDOS trước và Linux cũng vậy (UNIX). Nhiều người nói rằng MS killed MSDOS. Thực sự là không (tôi đã chứng mình bằng lệnh mem ở trên) nhưng quá trình khởi động MS DOS ở Windows XP đã trở nên trong suốt hơn so với các Windows 98 trở về trước.
    Windows và Linux được phát triển lên từ C++, một ngôn ngữ Hướng Đối Tượng hoàn toàn và nó làm nhẹ nhàng hơn trong quá trình phát triển ứng dụng với ngôn ngữ C (Nhiều bạn không phân biệt được C và C++ khác nhau ở chỗ nào? Đó chính là cách nhìn về Hướng Đối Tượng).

    Object Pascal cũng có Hướng Đối Tượng nhưng không thể hiện được lý thuyết lớn lao đó. Vì khái niệm “Memory Management” chỉ có ở ngôn ngữ C/C++. Và chỉ với C++ MS mới tổ chức được hệ thống RAM như vậy.

    Rõ ràng nếu muốn viết 1 HĐH chúng ta chỉ có thể bắt đầu bằng 2 cách
    - Bắt đầu từ con số 0 giống như MS. Viết chay MS DOS bằng 1 ngôn ngữ máy.
    Hoặc là:
    - Chọn nền tảng Unix (Nếu MS DOS thì dù có thành công thì cũng bị MS nó phạt vì nó là độc quyền của MS) để phát triển và ngôn ngữ nên chọn chắc vẫn là C++ (Cái này là sự thật chứ không phải mình “lăng xê” đâu ) . Mình cũng đã thấy 1 nhóm sinh viên Việt Nam phát triển thành công 1 HDH bằng con đường chọn nền tảng là của Unix.
    Được sửa bởi eXecutive lúc 20:36 ngày 22-09-2007

  6. #6
    Tham gia
    12-02-2007
    Location
    HCM - NT
    Bài viết
    218
    Like
    0
    Thanked 1 Time in 1 Post
    VII. CON TRỎ HANDLE^ VÀ C++/CLI, BÍ ẨN CỦA NỀN TẢNG .NET

    Các bạn Click Here để đọc tiếp!

    Một lần nữa mình cám ơn các bạn đã cố gắng đọc những lý thuyết khô khan này.
    Được sửa bởi eXecutive lúc 11:02 ngày 28-09-2007

  7. #7
    Tham gia
    12-04-2007
    Location
    Việt Nam Quê Hương tui
    Bài viết
    241
    Like
    0
    Thanked 0 Times in 0 Posts
    Cám ơn Executive. Bài viết rất chi tiết và dễ hiểu. Co j` anh cho em xin them mot vai bai tap ve no nua. De em co the luyen tap no ky hon.
    Được sửa bởi mokona lúc 00:50 ngày 23-09-2007

  8. #8
    Tham gia
    04-11-2006
    Bài viết
    100
    Like
    0
    Thanked 0 Times in 0 Posts
    Bài viết rất hay, cảm ơn eXecutive nhiều

  9. #9
    Tham gia
    12-02-2007
    Location
    HCM - NT
    Bài viết
    218
    Like
    0
    Thanked 1 Time in 1 Post
    Ùm. Mình cám ơn! Mình cảm thấy rất vui khi có một ai đó cám ơn mình.

  10. #10
    Tham gia
    12-04-2007
    Location
    Việt Nam Quê Hương tui
    Bài viết
    241
    Like
    0
    Thanked 0 Times in 0 Posts
    Bài viết thật lôi cuốn nhưng sao đợi mãi mà vẫn chưa thấy part 2 nhỉ. Anh executive có thể soạn nhanh hơn được ko? Thanks

Trang 1 / 10 12346 ... LastLast

Bookmarks

Quy định

  • Bạn không thể tạo chủ đề mới
  • Bạn không thể trả lời bài viết
  • Bạn không thể gửi file đính kèm
  • Bạn không thể sửa bài viết của mình
  •