2016-12-05 39 views
9

Như tôi đã tìm hiểu về lắp ráp, tôi đã sử dụng GDB theo cách sau:Làm thế nào để đọc sổ đăng ký CPU bằng cách sử dụng trình gỡ lỗi chạy trên cùng một CPU?

gdb ./a.out (a is a compiled C script that only prints hello world) 
break main 
run 
info registers 

Tại sao tôi có thể nhìn thấy các thanh ghi được sử dụng bởi chương trình của tôi khi tôi bản thân mình bằng cách sử dụng CPU cùng để in các thanh ghi? Không nên sử dụng GDB (hoặc hệ điều hành) ghi đè lên các thanh ghi và chỉ hiển thị cho tôi các thanh ghi ghi đè? Câu trả lời duy nhất tôi có thể nghĩ đến là một thực tế là CPU của tôi là lõi kép và một trong các lõi đang được sử dụng và phần còn lại được giữ lại cho chương trình.

+2

Câu hỏi khái niệm hay. Trong quá trình học tập của bạn, hãy chắc chắn xem xét cách 'stack stack' và' pointer pointer' được điều khiển. _One_ cách để sử dụng thanh ghi, và vẫn biết những gì họ _were_, là để đẩy chúng vào ông ngăn xếp trước khi bạn thay đổi chúng. Bởi vì bạn biết có bao nhiêu byte bạn đã đẩy lên ngăn xếp, thậm chí bạn có thể suy ra con trỏ ngăn xếp trước khi bạn bắt đầu thay đổi mọi thứ. Tuy nhiên, nhiều CPU có một hướng dẫn nhanh để sao chép tất cả các thanh ghi đến/từ bộ đệm. Chủ yếu được sử dụng để trao đổi các quy trình ra để CPU và đăng ký có thể được chia sẻ, nhưng một trình gỡ lỗi thực hiện điều này cũng. –

Trả lời

14

Hệ điều hành duy trì trạng thái của thanh ghi cho mỗi chuỗi thực hiện. Khi bạn kiểm tra sổ đăng ký trong gdb, trình gỡ lỗi thực sự yêu cầu hệ điều hành đọc giá trị đăng ký từ trạng thái đã lưu. Chương trình của bạn không chạy vào thời điểm đó, đó là trình gỡ rối.

Giả sử không có quy trình nào khác trên hệ thống của bạn. Dưới đây là một cái nhìn đơn giản về những gì sẽ xảy ra:

  1. Debugger ra mắt và nhận được cpu
  2. Debugger hỏi hệ điều hành để tải chương trình của bạn
  3. Debugger hỏi hệ điều hành để đặt breakpoint
  4. Debugger hỏi hệ điều hành để bắt đầu thực hiện chương trình của bạn. Hệ điều hành lưu trạng thái đăng ký gdb và điều khiển chuyển đến chương trình của bạn.
  5. Chương trình của bạn truy cập điểm ngắt. Hệ điều hành kiểm soát, lưu trạng thái đăng ký của chương trình của bạn, tải lại thanh ghi gdb và cung cấp cho CPU trở lại gdb.
  6. Trình gỡ lỗi yêu cầu hệ điều hành đọc sổ đăng ký của chương trình từ trạng thái đã lưu.

Lưu ý rằng cơ chế này là một phần của các nhiệm vụ thông thường của hệ điều hành đa nhiệm, nó không phải là cụ thể để gỡ lỗi. Khi trình lên lịch hệ điều hành quyết định một chương trình khác nên thực hiện, nó sẽ lưu trạng thái hiện tại và tải một trạng thái khác. Điều này được gọi là một chuyển đổi ngữ cảnh và nó có thể xảy ra nhiều lần mỗi giây, tạo ra ảo tưởng rằng các chương trình thực thi đồng thời ngay cả khi bạn chỉ có một lõi cpu đơn lẻ.

+1

Trạng thái được lưu vào bộ nhớ khi "chuyển đổi" của chuỗi. Trình gỡ lỗi đặt điểm ngắt vào mã máy của bạn để thay thế lệnh đích, chạy mã của bạn, nó sẽ nhấn breakpoint ('int 03h' thường, vì nó là mã byte đơn, vì vậy nó có thể thay thế bất kỳ lệnh nào) và trình xử lý ngắt (breakpoint) sẽ lưu tất cả các thanh ghi vào bộ nhớ trước khi nó sẽ sử dụng chúng để xử lý sự kiện của chính nó, và điều khiển chuyển đổi tới trình gỡ lỗi, với thông tin nơi trạng thái ngắt + đã được lưu. EDIT: nah, bạn thêm thông tin nhiều hơn .. và chính xác hơn, tôi thấy tôi sắp xếp vẫn còn trong "chế độ thực": D – Ped7g

+1

Syscall cho phép một quá trình đọc đăng ký của quá trình khác (và bộ nhớ) là gỡ lỗi cụ thể, mặc dù. – dbrank0

5

Quay lại những ngày cũ của các hệ điều hành tác vụ đơn lẻ, những thứ duy nhất có thể cản trở việc thực thi chương trình của bạn bị gián đoạn. Bây giờ, các trình xử lý ngắt có cùng vấn đề mà bạn đang nói, chương trình của bạn đang tính toán điều gì đó, người dùng nhấn phím - ngắt - thường xuyên dịch vụ ngắt để thực hiện một số công việc, nhưng không được sửa đổi một thanh ghi duy nhất trong quy trình . Đó là lý do chính, ngăn xếp được phát minh ở nơi đầu tiên. Một thói quen dịch vụ 80x86 DOS ngắt thông thường sẽ trông như thế này:

push ax 
push cx 
push dx 
push bx 
push si 
push di 
push bp 
// no need to push sp 
[do actual work, caller registers avaiable on stack if needed] 
pop bp 
pop di 
pop si 
pop bx 
pop dx 
pop cx 
pop ax 
iret 

này thậm chí còn rất phổ biến, đó là một cặp mới hướng dẫn pushapopa (đối với push/pop tất cả) được tạo ra để giảm bớt nhiệm vụ này. Trong các CPU ngày nay có cách ly không gian địa chỉ giữa các hệ điều hành và ứng dụng, CPU cung cấp một số hệ thống trạng thái nhiệm vụ và cho phép hệ điều hành chuyển đổi công việc (ngắt có thể vẫn hoạt động tương tự như đã nêu ở trên, nhưng cũng có thể được xử lý thông qua tác vụ.). chuyển đổi). Tất cả các hệ điều hành hiện đại đều sử dụng hệ thống trạng thái nhiệm vụ này, nơi mà CPU lưu tất cả các thanh ghi của một tiến trình trong khi nó không được thực thi một cách chủ động. Giống như Jester đã được giải thích, gdb chỉ yêu cầu hệ điều hành cho các giá trị này trên quy trình được gỡ lỗi và sau đó in chúng.

Các vấn đề liên quan