如何获取NASM汇编程序的运行时?

huangapple go评论70阅读模式
英文:

How to get the runtime of a NASM assembly program?

问题

I'll provide the translation of the text you provided without the code part:

如何获取NASM程序的运行时间?
这是我想要获取运行时间的程序。这是一个使用NASM汇编来计算斐波那契数列的简单程序,所以我需要获取该程序的运行时间,以便与我的其他算法进行速度比较。

有没有特殊的系统调用可供调用?我尝试了谷歌和各种其他方法,但都没有成功。

英文:

How get the Runtime of a NASM Program?

This is the program that I want to get the runtime of it. It is a simple program to calculate the Fibonacci sequence using NASM assembly so, I need to get the runtime of the this program to compare the speed with my other algorithms:

;fib.asm

global  main
extern  printf

section .text

main:
        push    rbx                     

        mov     ecx, 90                
        xor     rax, rax              
        xor     rbx, rbx                
        inc     rbx                    
print:
        push    rax                    
        push    rcx                     

        mov     rdi, format            
        mov     rsi, rax                
        xor     rax, rax                

        call    printf                  

        pop     rcx                   
        pop     rax                   

        mov     rdx, rax              
        mov     rax, rbx                
        add     rbx, rdx                
        dec     ecx                     
        jnz     print                   

        pop     rbx                     
        ret
format:
        db  "%20ld", 10, 0

Is there any special syscall to invoke for that. I tried googling and various other methods but none of it worked for me.

答案1

得分: 1

以下是代码中需要翻译的部分:

如果您询问程序运行的时间,而不是一些运行时库的辅助函数,比如printf,那么要做的方法是使用与任何其他程序都可以使用来测量其CPU使用率的系统调用。在Microsoft Win64上,这是GetProcessTime() API,它接受以下64位参数,请记住先推送最后一个参数,并在寄存器中传递前4个参数。

以下代码片段直接写在这个答案中,没有经过任何测试

GetTimeSoFar PROC NEAR
    ; 栈现在按16的倍数对齐
    sub rsp, 32  ; 用于返回变量和对齐的空间
    push -1      ; 当前进程的64位句柄
    sub rsp, 32  ; 用于4个参数的空间
    lea r9, [rsp+40]  ; 64位输出变量 creatTim 的地址
    lea r8, [rsp+48]  ; 64位临时变量 exitTim 的地址
    lea rdx, [rsp+56] ; 64位输出变量 kernTim 的地址
    lea rcx, [rsp+64] ; 64位输出变量 userTim 的地址
    ; 栈现在按16的倍数对齐,减去8
    mov rax, [__imp_GetProcessTime]
    call rax ; 或使用等效的 retpoline
    ; 栈现在按16的倍数对齐,减去8
    add rsp, 40  ; 删除参数空间和一个推送的参数
    pop r9       ; r9 现在是自1600年以来以100纳秒为单位的创建时间
    pop r8       ; r8 现在是退出时间的无效数据占位符
    pop rdx      ; rdx 现在是以100纳秒为单位的NT内核系统调用的时间
    pop rcx      ; rcx 现在是程序CPU用户模式运行时间,以100纳秒为单位
    ; 栈现在按16的倍数对齐
    ret          ; 或跳转到 retpoline 进行返回
GetTimeSoFar ENDP

GetLastErrorWrap PROC NEAR
    sub rsp, 40
    ; 栈现在按16的倍数对齐,减去8
    mov rax, [__imp_GetLastError]
    call rax ; 或使用等效的 retpoline
    add rsp, 40
    ; 栈现在按16的倍数对齐
    mov ecx, eax
    shr ecx, 16
    cmp cx, 8007h
    jne notWin32AsHRESULT
    movsx eax, cx
notWin32AsHRESULT:
    test eax, eax
    jne hasLastErr
    mov eax, 1297 ; ERROR_UNIDENTIFIED_ERROR
hasLastErr:
    ; 栈现在按16的倍数对齐
    ret          ; 或跳转到 retpoline 进行返回
GetLastErrorWrap ENDP

; 在主函数的顶部
sub rsp, localvarssize
; 栈现在按16的倍数对齐
push rdx ; 对齐栈
; 栈现在按16的倍数对齐,减去8
call GetTimeSoFar
pop rdx  ; 对齐栈
; 栈现在按16的倍数对齐
test rax, rax
jz failCheckLastErr;
mov [LocalVarWithValueBeforeRun], rcx

; TODO, TODO,在这里进行计算

push rdx ; 对齐栈
; 栈现在按16的倍数对齐,减去8
call GetTimeSoFar
pop rdx  ; 对齐栈
; 栈现在按16的倍数对齐
test rax, rax
jz failCheckLastErr;
sub rcx, [LocalVarWithValueBeforeRun]
mov r8, 10000000
mov rax, rcx
xor rdx, rdx
div r8
; rdx 现在是花费的秒数
; rax 现在是十进制秒数,以精确的7位数字打印
mov r8, rax
lea rcx, StrTimePrintf ; "Runtime=%I64u.%07us\n"
sub rsp, 40
; 栈现在按16的倍数对齐,减去8
call printf
add rsp, 40
; 栈现在按16的倍数对齐
; 在这里返回成功
xor rax, rax
add rsp, localvarssize
; 栈现在按16的倍数对齐
ret ; 或跳转到 retpoline 进行返回
failCheckLastErr:
sub rsp, 40   ; 用于变量区域和对齐填充的空间
; 栈现在按16的倍数对齐,减去8
call GetLastErrorWrap
mov [rsp + 32], eax  ; 在对齐填充区域保存错误代码
mov r8d, eax
mov edx, eax
lea rcx, StrTimeMeasFailed ; "\nGetProcesTime() failed err=%d(0x%08X)\n"
; 栈现在按16的倍数对齐,减去8
call printf
; 以系统退出代码返回错误代码
mov eax, [rsp + 32]
add rsp, localvarssize + 40
; 栈现在按16的倍数对齐
ret ; 或跳转到 retpoline 进行返回
英文:

If you are asking about the time the program runs, not some runtime library of helper functions such as printf, then the way to do that is to use the same system calls that any other program could use to measure its CPU usage. On Microsoft Win64, this is the GetProcessTime() API, which takes the following 64 bit arguments, remember to push the last argument first and to pass the first 4 arguments in registers
The following code snippet is written directly in this answer and not tested at all

GetTimeSoFar PROC NEAR
    ; Stack is now aligned at multiple of 16
    sub rsp,32  ; Space for return vars and alignment
    push -1     ; 64 bit handle for the current process
    sub rsp,32  ; Space for 4 args
    lea r9,[rsp+40]  ; address of a 64 bit output var for creatTim
    lea r8,[rsp+48]  ; address of a 64 bit scratch var for exitTim
    lea rdx,[rsp+56] ; address of a 64 bit output var for kernTim
    lea rcx,[rsp+64] ; address of a 64 bit output var for userTim
    ; Stack is now aligned at multiple of 16 minus 8
    mov rax,[__imp_GetProcesTime]
    call rax ; Or use equivalent retpoline
    ; Stack is now aligned at multiple of 16 minus 8
    add rsp,40  ; Remove arg space and one pushed arg
    pop r9      ; r9 is now creation time in 100ns units since year 1600
    pop r8      ; r8 is now invalid data placeholder for exit time
    pop rdx     ; rdx is now time spent in NT kernel syscalls in 100ns units
    pop rcx     ; rcx in now program CPU user mode runtime in 100ns units.
    ; Stack is now aligned at multiple of 16
    ret         ; Or jump to retpoline for return
GetTimeSoFar ENDP

GetLastErrorWrap PROC NEAR
    sub rsp,40
    ; Stack is now aligned at multiple of 16 minus 8
    mov rax,[__imp_GetLastError]
    call rax ; Or use equivalent retpoline
    add rsp,40
    ; Stack is now aligned at multiple of 16
    mov ecx,eax
    shr ecx,16
    cmp cx,8007h
    jne notWin32AsHRESULT
    movsx eax,cx
notWin32AsHRESULT: 
    test eax,eax
    jne hasLastErr
    mov eax,1297 ; ERROR_UNIDENTIFIED_ERROR
hasLastErr:
    ; Stack is now aligned at multiple of 16
    ret         ; Or jump to retpoline for return
GetLastErrorWrap ENDP

    ; At top of main function
    sub rsp,localvarssize
    ; Stack is now aligned at multiple of 16
    push rdx ; Align stack
    ; Stack is now aligned at multiple of 16 minus 8
    call GetTimeSoFar
    pop rdx  ; Align stack
    ; Stack is now aligned at multiple of 16
    test rax,rax
    jz failCheckLastErr;
    mov [LocalVarWithValueBeforeRun], rcx

    ; TODO, TODO, Put calculations here

    push rdx ; Align stack
    ; Stack is now aligned at multiple of 16 minus 8
    call GetTimeSoFar
    pop rdx  ; Align stack
    ; Stack is now aligned at multiple of 16
    test rax,rax
    jz failCheckLastErr;
    sub rcx,[LocalVarWithValueBeforeRun]
    mov r8,10000000
    mov rax,rcx
    xor rdx,rdx
    div r8
    ; rdx is now seconds spent
    ; rax is now decimal seconds spent, printf as exactly 7 digits
    mov r8,rax
    lea rcx,StrTimePrintf ; "Runtime=%I64u.%07us\n"
    sub rsp,40
    ; Stack is now aligned at multiple of 16 minus 8
    call printf
    add rsp,40
    ; Stack is now aligned at multiple of 16
    ; Return success here
    xor rax,rax
    add rsp,localvarssize
    ; Stack is now aligned at multiple of 16
    ret ; Or jump to retpoline for return
failCheckLastErr:
    sub rsp,40   ; Scratch space for var area and alignment padding
    ; Stack is now aligned at multiple of 16 minus 8
    call GetLastErrorWrap
    mov [rsp + 32],eax  ; Save error code in alignment pad area
    mov r8d,eax
    mov edx,eax
    lea rcx,StrTimeMeasFailed ; "\nGetProcesTime() failed err=%d(0x%08X)\n"
    ; Stack is now aligned at multiple of 16 minus 8
    call printf
    ; Return error code as system exit code
    mov eax,[rsp + 32]
    add rsp,localvarssize + 40
    ; Stack is now aligned at multiple of 16
    ret ; Or jump to retpoline for return

huangapple
  • 本文由 发表于 2023年6月21日 23:25:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76524901.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定