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

klr1opcd  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(140)

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

这是我想要的程序的运行时间。这是一个简单的程序来计算斐波那契序列使用NASM汇编,所以,我需要得到这个程序的运行时间来比较速度与我的其他算法:

;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

是否有任何特殊的系统调用。我尝试了谷歌搜索和其他各种方法,但没有一个对我有用。

xwmevbvl

xwmevbvl1#

如果你问的是程序运行的时间,而不是一些运行时的帮助函数库,如printf,那么方法就是使用任何其他程序都可以用来测量其CPU使用率的相同系统调用。在Microsoft Win64上,这是GetProcessTime()API,它接受以下64位参数,请记住首先推送最后一个参数,并将前4个参数传递到寄存器中。以下代码片段直接在此答案中编写,根本未进行测试

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

相关问题