История изменений
Исправление cudeta, (текущая версия) :
что именно Вы бы написали по-другому?
Это бездарный мусор, который наглядно демонстрирует, зачем нужен компилятор.
mov rdx, 0 ; Automatic protocol.
xor rdx, rdx
— рекомендованный Intel и AMD способ занулить регистр. Это называется zero idiom, оно занимает меньше места, чем mov rdx, 0
и распознаётся на уровне декодирования инструкций.
cmp rax, 0
test rax, rax
занимает меньше места и выставляет те же флаги.
cld ; Move forward
mov ecx, 19 ; Length is 19 with the null terminator.
rep movsb ; Copy.
Это гораздо медленнее, чем тупо скопировать через mov 8+8+2+1 байт.
lea rsi, [rsp]
mov rsi, rsp
imul rax, 8 ; sizeof(format) == 8
В этом контексте (флаги не проверяются) эквивалентно shl rax, 3
либо (в синтаксисе AT&T, не силён в интеловском) leaq (,8,%rax), %rax
.
mov BYTE [rsp + 3*4 + 0], 'f' mov BYTE [rsp + 3*4 + 1], 'i' mov BYTE [rsp + 3*4 + 2], 'x' mov BYTE [rsp + 3*4 + 3], 'e' mov BYTE [rsp + 3*4 + 4], 'd'
Зачем, если можно через два mov это сделать?
; Compute padding and packet u32 count with division and modulo 4. mov eax, edx ; Put dividend in eax. mov ecx, 4 ; Put divisor in ecx. cdq ; Sign extend. idiv ecx ; Compute eax / ecx, and put the remainder (i.e. modulo) in edx. ; LLVM optimizer magic: `(4-x)%4 == -x & 3`, for some reason. neg edx and edx, 3 mov r9d, edx ; Store padding in r9.
Особая одарённость, сложно это даже как-то прокомментировать.
cld ; Move forward mov ecx, r8d ; String length. rep movsb ; Copy.
Это очень неоптимально, см. как реализован memcpy в glibc.
; Read the server response: read(2). ; Use the stack for the read buffer. ; The X11 server first replies with 8 bytes. Once these are read, it replies with a much bigger message. mov rax, SYSCALL_READ mov rdi, rdi lea rsi, [rsp] mov rdx, 8 syscall cmp rax, 8 ; Check that the server replied with 8 bytes. jnz die
; Read the rest of the server response: read(2). ; Use the stack for the read buffer. mov rax, SYSCALL_READ mov rdi, rdi lea rsi, [rsp] mov rdx, 1<<15 syscall cmp rax, 0 ; Check that the server replied with something. jle die
SOCK_STREAM так не работает.
Note: There is an optimization method that uses rbp as a standard register (with a C compiler, that’s the flag -fomit-frame-pointer), which means we lose the information about the call stack. My advice is: never do this, it is no worth it.
-fomit-frame-pointer это умолчание на x86-64.
Исходная версия cudeta, :
что именно Вы бы написали по-другому?
Это бездарный мусор, который наглядно демонстрирует, зачем нужен компилятор.
mov rdx, 0 ; Automatic protocol.
xor rdx, rdx
— рекомендованный Intel и AMD способ занулить регистр. Это называется zero idiom, оно занимает меньше места, чем mov rdx, 0
и распознаётся на уровне декодирования инструкций.
cmp rax, 0
test rax, rax
занимает меньше места и выставляет те же флаги.
cld ; Move forward
mov ecx, 19 ; Length is 19 with the null terminator.
rep movsb ; Copy.
Это гораздо медленнее, чем тупо скопировать через mov 8+8+2+1 байт.
lea rsi, [rsp]
mov rsi, rsp
imul rax, 8 ; sizeof(format) == 8
В этом контексте (флаги не проверяются) эквивалентно shl rax, 3
.
mov BYTE [rsp + 3*4 + 0], 'f' mov BYTE [rsp + 3*4 + 1], 'i' mov BYTE [rsp + 3*4 + 2], 'x' mov BYTE [rsp + 3*4 + 3], 'e' mov BYTE [rsp + 3*4 + 4], 'd'
Зачем, если можно через два mov это сделать?
; Compute padding and packet u32 count with division and modulo 4. mov eax, edx ; Put dividend in eax. mov ecx, 4 ; Put divisor in ecx. cdq ; Sign extend. idiv ecx ; Compute eax / ecx, and put the remainder (i.e. modulo) in edx. ; LLVM optimizer magic: `(4-x)%4 == -x & 3`, for some reason. neg edx and edx, 3 mov r9d, edx ; Store padding in r9.
Особая одарённость, сложно это даже как-то прокомментировать.
cld ; Move forward mov ecx, r8d ; String length. rep movsb ; Copy.
Это очень неоптимально, см. как реализован memcpy в glibc.
; Read the server response: read(2). ; Use the stack for the read buffer. ; The X11 server first replies with 8 bytes. Once these are read, it replies with a much bigger message. mov rax, SYSCALL_READ mov rdi, rdi lea rsi, [rsp] mov rdx, 8 syscall cmp rax, 8 ; Check that the server replied with 8 bytes. jnz die
; Read the rest of the server response: read(2). ; Use the stack for the read buffer. mov rax, SYSCALL_READ mov rdi, rdi lea rsi, [rsp] mov rdx, 1<<15 syscall cmp rax, 0 ; Check that the server replied with something. jle die
SOCK_STREAM так не работает.
Note: There is an optimization method that uses rbp as a standard register (with a C compiler, that’s the flag -fomit-frame-pointer), which means we lose the information about the call stack. My advice is: never do this, it is no worth it.
-fomit-frame-pointer это умолчание на x86-64.