【发布时间】:2020-04-25 23:42:40
【问题描述】:
我只是在学习 NASM,如果我犯了一些明显的错误,我很抱歉,但我不明白我做错了什么。
请查看下面的代码,让我知道什么是不正确的。它编译并运行正常,但结果打印垃圾。
我知道来自mach_absolute_time 的信息取决于硬件,因此需要使用来自mach_timebase_info 的结构中的信息进行调整。
我创建了以下测试程序,人为地执行需要 1 秒。 它打印开始、结束和经过的绝对马赫时间信息(奇怪的是,在我的机器上显示正确的纳秒数)。 但是计算出的纳秒是垃圾 - 可能与我在数学/使用 xmm 寄存器和数据大小时犯的一些错误有关,但为了我的爱,我无法弄清楚。 感谢您的帮助!
; ----------------------------------------------------------------------------------------
; Testing mach_absolute_time
; nasm -fmacho64 mach.asm && gcc -o mach mach.o
; ----------------------------------------------------------------------------------------
global _main
extern _printf
extern _mach_absolute_time
extern _mach_timebase_info
extern _nanosleep
default rel
section .text
_main:
push rbx ; aligns the stack x C calls
; start measurement
call _mach_absolute_time ; get the absolute time hardware dependant
mov [start], rax ; save start in start
; print start
lea rdi, [time_absolute]
mov rsi, rax
call _printf
; do some time intensive stuff - This simulates 1 sec work
lea rdi, [timeval]
call _nanosleep
; end measurement
call _mach_absolute_time
mov [end], rax
; print end
lea rdi, [time_absolute]
mov rsi, rax
call _printf
; calc elapsed
mov r10d, [end]
mov r11d, [start]
sub r10d, r11d ; r10d = end - start
mov [diff], r10d ; copy to diff
mov rax, [diff] ; diff to rax to print as int
cvtsi2ss xmm2, r10d ; diff to xmm2 to calc nanoseconds
; print elapsed
lea rdi, [diff_absolute]
mov rsi, rax
call _printf
; get conversion factor to get nanoseconds and store numerator and denominator
; in xmm0 and xmm1
lea rdi, [timebase_info]
call _mach_timebase_info ; get conversion factor to nanoseconds
movss xmm0, [numer]
movss xmm1, [denom]
; print numerator & denominator as float to ensure I am getting the info into xmm regs
lea rdi, [time_base]
mov rax, 2
call _printf
; calc nanoseconds - xmm0 ends with nanoseconds
mulss xmm0, xmm2 ; multiply elapsed * numerator
divss xmm0, xmm1 ; divide by the denominator
; print nanoseconds as float
lea rdi, [nanosecs_calc]
mov rax, 1 ; 1 non-int argument
call _printf
pop rbx ; undoes the stack alignment push
ret
section .data
; _mach_timebase_info call struct
timebase_info:
numer db 8
denom db 8
; lazy way to set up 1 sec wait
timeval:
tv_sec dq 1
tv_usec dq 0
time_absolute: db "mach_absoute_time: %ld", 10, 0
diff_absolute: db "absoute_time diff: %ld", 10, 0
time_base: db "numerator: %g, denominator: %g", 10, 0
nanosecs_calc: db "calc nanoseconds: %ld", 10, 0
; using %g format also prints garbage
; nanosecs_calc: db "calc nanoseconds: %g", 10, 0
; should use registers but for clarity
start: dq 0
end: dq 0
diff: dq 0
【问题讨论】: