CHAPTER 18. ARRAYS CHAPTER 18. ARRAYS
Listing 18.18: Optimizing MSVC 2013 x64
$SG3143 DB 'm', 00H, 'o', 00H, 'n', 00H, 't', 00H, 'h', 00H, '.', 00H
DB 'c', 00H, 00H, 00H
$SG3144 DB 'm', 00H, 'o', 00H, 'n', 00H, 't', 00H, 'h', 00H, '<', 00H
DB '1', 00H, '2', 00H, 00H, 00H
month$ = 48
get_month1_checked PROC
$LN5:
push rbx
sub rsp, 32
movsxd rbx, ecx
cmp ebx, 12
jl SHORT $LN3@get_month1
lea rdx, OFFSET FLAT:$SG3143
lea rcx, OFFSET FLAT:$SG3144
mov r8d, 29
call _wassert
$LN3@get_month1:
lea rcx, OFFSET FLAT:month1
mov rax, QWORD PTR [rcx+rbx*8]
add rsp, 32
pop rbx
ret 0
get_month1_checked ENDP
In fact, assert() is not a function, but macro. It checks for a condition, then passes also the line number and file name to
another function which reports this information to the user. Here we see that both file name and condition are encoded in
UTF-16. The line number is also passed (it’s 29).
This mechanism is probably the same in all compilers. Here is what GCC does:
Listing 18.19: Optimizing GCC 4.9 x64
.LC1:
.string "month.c"
.LC2:
.string "month<12"
get_month1_checked:
cmp edi, 11
jg .L6
movsx rdi, edi
mov rax, QWORD PTR month1[0+rdi*8]
ret
.L6:
push rax
mov ecx, OFFSET FLAT:__PRETTY_FUNCTION.2423
mov edx, 29
mov esi, OFFSET FLAT:.LC1
mov edi, OFFSET FLAT:.LC2
call assert_fail
__PRETTY_FUNCTION__.2423:
.string "get_month1_checked"
So the macro in GCC also passes the function name for convenience.
Nothing is really free, and this is true for the sanitizing checks as well. They make your program slower, especially if the
assert() macros used in small time-critical functions. So MSVC, for example, leaves the checks in debug builds, but in release
builds they all disappear.
MicrosoftWindows NTkernels come in “checked” and “free” builds^12. The first has validation checks (hence, “checked”), the
second one doesn’t (hence, “free” of checks).
(^12) msdn.microsoft.com/en-us/library/windows/hardware/ff543450(v=vs.85).aspx