2015-07-23 17 views
5

Tôi muốn tăng ngoại lệ trong khối khối as64.Làm cách nào để tăng ngoại lệ trong khối asm?

Hãy giả sử tôi có một chức năng như vậy:

function Example(Values: array of integer): integer; 
asm 
    or rcx,rcx 
    jz @error 
    .... 

Tôi biết tôi chỉ có thể đọc các con trỏ và có được một AV, tuy nhiên tôi muốn nêu lên một lỗi mô tả nhiều hơn.

tôi có thể thực hiện một chức năng bổ sung và gọi đó là một:

asm 
    or rcx,rcx 
    jz @error 
    .... 
@error: 
    mov ecx, 1 
    mov rdx, ErrorString 
    jmp RaiseError 
    .... 

function RaiseError(code: integer; const Msg: string); 
begin 
    case code of 
    1: raise EEmptyArrayError.Create(Msg); 

Tuy nhiên các lỗi sau đó sẽ xảy ra bên ngoài hàm trong đó là được gây ra. Làm cách nào để ngoại lệ (dường như) bắt nguồn từ bên trong hàm Example.

Lưu ý rằng đây là X64, vì vậy tất cả các câu trả lời SEH áp dụng cho X86 đều không tốt vì X64 sử dụng VEH.

+2

Tôi nghĩ rằng nó vẫn là SEH trong x64. Và chỉ cần viết một số Pascal và xem những gì trình biên dịch phát ra để làm việc nó ra. –

+1

Vì không ai khác sẽ hỏi, nếu mã là đủ cao mà bạn muốn nó để nâng cao ngoại lệ, tại sao bạn viết nó trong hội đồng ở nơi đầu tiên? – alcalde

+0

Bởi vì nó cần hướng dẫn SSE, và tôi không có SSE-intrinsics. – Johan

Trả lời

4

Cú pháp đầy đủ của tăng là:

raise Exception at address 

Tất cả bạn cần làm là để vượt qua IP hiện tại như một tham số và các proc lỗi có thể vượt qua mà sang ngoại lệ.

Bạn có thể nhận RIP sử dụng lea rax, [rip].

Như vậy mã trở thành:

asm 
    or rcx,rcx 
    jz @error 
    .... 
@error: 
    mov ecx, 1 
    mov rdx, ErrorString 
    lea r8,[rip] 
    jmp RaiseError 
    .... 

function RaiseError(code: integer; const Msg: string; address: pointer); 
begin 
    case code of 
    1: raise EEmptyArrayError.Create(Msg) at address; 

Tất nhiên trong trường hợp này nó dễ dàng hơn để sử dụng

function RaiseError(code: integer; const Msg: string); 
begin 
    case code of 
    1: raise EEmptyArrayError.Create(Msg) at ReturnAddress; 

Note
Trong trường hợp này nếu bạn giữ cho jmp lỗi sẽ dường như bắt nguồn từ thói quen gọi điện, trong trường hợp này thực sự là chính xác. Nếu bạn muốn ngoại lệ chỉ ngón tay có lỗi vào mã asm của bạn thì hãy sử dụng cuộc gọi.

+3

Trong Delphi XE2 +, bạn có thể (và nên) sử dụng trình biên dịch 'System.ReturnAddress' nội tại, hoạt động trong cả 32bit và 64bit:' thủ tục RaiseError (mã: số nguyên; const Msg: string); bắt đầu ... nâng cao EEmptyArrayError.Create (Msg) tại ReturnAddress; ... kết thúc; ' –

+0

Tôi nghĩ bạn phải sử dụng' gọi RaiseError' thay vì 'jmp RaiseError' khi sử dụng phiên bản' RaiseError' với 'ReturnAddress'. – JRL

+0

@JRL Không có jmp là chính xác. Trong trường hợp này, lỗi không nằm trong mã asm của tôi, lỗi trong thường trình gọi mã đó với tham số nil. ngoại lệ sẽ hiển thị điều đó. nếu không, người dùng sẽ gỡ lỗi thường trình sai. – Johan

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