Last active
October 21, 2025 07:29
-
-
Save isopen/25c4829daffb3880a32fac1f85f5f888 to your computer and use it in GitHub Desktop.
gas_tdjson_example.s
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # TDLib Minimal Linux Client in x86-64 GNU Assembler | |
| # | |
| # as -o gas_tdjson_example.o gas_tdjson_example.s | |
| # gcc -o gas_tdjson_example gas_tdjson_example.o -ldl -no-pie | |
| # ./gas_tdjson_example | |
| .section .data | |
| # Error messages | |
| lib_error: .asciz "Error: libtdjson.so not found\n" | |
| client_error: .asciz "Error: Failed to create client\n" | |
| input_error: .asciz "Error reading input\n" | |
| receive_error: .asciz "Error in receive function\n" | |
| # Function names | |
| create_name: .asciz "td_json_client_create" | |
| send_name: .asciz "td_json_client_send" | |
| receive_name: .asciz "td_json_client_receive" | |
| destroy_name: .asciz "td_json_client_destroy" | |
| execute_name: .asciz "td_json_client_execute" | |
| # Library name | |
| lib_name: .asciz "libtdjson.so" | |
| # Prompts | |
| phone_prompt: .asciz "Enter phone number (international format): " | |
| code_prompt: .asciz "Enter authentication code: " | |
| password_prompt: .asciz "Enter password: " | |
| auth_success: .asciz "Authorization successful!\n" | |
| auth_wait: .asciz "Waiting for authorization...\n" | |
| # JSON messages | |
| params_msg: .asciz "{\"@type\":\"setTdlibParameters\",\"database_directory\":\"td_data\",\"use_message_database\":true,\"api_id\":94575,\"api_hash\":\"a3406de8d171bb422bb6ddf3bbd800e2\",\"system_language_code\":\"en\",\"device_model\":\"AsmClient\",\"application_version\":\"1.0\"}" | |
| verbosity_msg: .asciz "{\"@type\":\"setLogVerbosityLevel\",\"new_verbosity_level\":2}" | |
| close_msg: .asciz "{\"@type\":\"close\"}" | |
| newline: .asciz "\n" | |
| # Authorization states | |
| auth_wait_phone: .asciz "authorizationStateWaitPhoneNumber" | |
| auth_wait_code: .asciz "authorizationStateWaitCode" | |
| auth_wait_password: .asciz "authorizationStateWaitPassword" | |
| auth_ready: .asciz "authorizationStateReady" | |
| # Format strings | |
| fmt_phone: .asciz "{\"@type\":\"setAuthenticationPhoneNumber\",\"phone_number\":\"%s\"}" | |
| fmt_code: .asciz "{\"@type\":\"checkAuthenticationCode\",\"code\":\"%s\"}" | |
| fmt_password: .asciz "{\"@type\":\"checkAuthenticationPassword\",\"password\":\"%s\"}" | |
| .section .bss | |
| # Handle pointers | |
| .lcomm lib_handle, 8 | |
| .lcomm client_handle, 8 | |
| # Function pointers | |
| .lcomm create_func, 8 | |
| .lcomm send_func, 8 | |
| .lcomm receive_func, 8 | |
| .lcomm destroy_func, 8 | |
| .lcomm execute_func, 8 | |
| # Buffers | |
| .lcomm input_buffer, 256 | |
| .lcomm phone_buffer, 32 | |
| .lcomm code_buffer, 16 | |
| .lcomm password_buffer, 64 | |
| .lcomm json_buffer, 1024 | |
| .lcomm auth_state, 8 | |
| .section .text | |
| .globl main | |
| .extern dlopen | |
| .extern dlsym | |
| .extern printf | |
| .extern sleep | |
| .extern exit | |
| .extern fgets | |
| .extern stdin | |
| .extern strstr | |
| .extern sprintf | |
| .extern strlen | |
| .extern putchar | |
| .extern usleep | |
| .extern fflush | |
| main: | |
| pushq %rbp | |
| movq %rsp, %rbp | |
| subq $32, %rsp | |
| # Load TDLib library | |
| movq $lib_name, %rdi | |
| movq $1, %rsi | |
| call dlopen | |
| testq %rax, %rax | |
| jz .dl_error | |
| movq %rax, lib_handle(%rip) | |
| # Get function addresses | |
| movq lib_handle(%rip), %rdi | |
| movq $create_name, %rsi | |
| call dlsym | |
| movq %rax, create_func(%rip) | |
| movq lib_handle(%rip), %rdi | |
| movq $send_name, %rsi | |
| call dlsym | |
| movq %rax, send_func(%rip) | |
| movq lib_handle(%rip), %rdi | |
| movq $receive_name, %rsi | |
| call dlsym | |
| movq %rax, receive_func(%rip) | |
| movq lib_handle(%rip), %rdi | |
| movq $destroy_name, %rsi | |
| call dlsym | |
| movq %rax, destroy_func(%rip) | |
| movq lib_handle(%rip), %rdi | |
| movq $execute_name, %rsi | |
| call dlsym | |
| movq %rax, execute_func(%rip) | |
| # Create TDLib client | |
| movq create_func(%rip), %rax | |
| call *%rax | |
| testq %rax, %rax | |
| jz .client_error | |
| movq %rax, client_handle(%rip) | |
| # Set log verbosity | |
| movq client_handle(%rip), %rdi | |
| movq $verbosity_msg, %rsi | |
| movq execute_func(%rip), %rax | |
| call *%rax | |
| # Set TDLib parameters | |
| movq client_handle(%rip), %rdi | |
| movq $params_msg, %rsi | |
| movq send_func(%rip), %rax | |
| call *%rax | |
| # Authorization loop | |
| xorq %r12, %r12 | |
| movq $0, auth_state(%rip) | |
| movq $50000, %rdi | |
| call usleep | |
| .auth_loop: | |
| movq client_handle(%rip), %rdi | |
| xorq %rsi, %rsi | |
| movq receive_func(%rip), %rax | |
| call *%rax | |
| testq %rax, %rax | |
| jz .no_message | |
| # Process message | |
| movq %rax, %rdi | |
| call process_message | |
| cmpq $1, %r12 | |
| je .auth_complete | |
| .no_message: | |
| # Check if we need to request input | |
| cmpq $1, auth_state(%rip) # wait_phone | |
| je .request_phone | |
| cmpq $2, auth_state(%rip) # wait_code | |
| je .request_code | |
| cmpq $3, auth_state(%rip) # wait_password | |
| je .request_password | |
| movq $10000, %rdi | |
| call usleep | |
| jmp .auth_loop | |
| .request_phone: | |
| movq $phone_prompt, %rdi | |
| call printf | |
| xorq %rdi, %rdi | |
| call fflush | |
| # Read phone number | |
| movq $phone_buffer, %rdi | |
| movq $32, %rsi | |
| movq stdin(%rip), %rdx | |
| call fgets | |
| testq %rax, %rax | |
| jz .input_error | |
| # Remove newline | |
| movq $phone_buffer, %rdi | |
| call remove_newline | |
| # Create JSON for phone number | |
| movq $json_buffer, %rdi | |
| movq $fmt_phone, %rsi | |
| movq $phone_buffer, %rdx | |
| call sprintf | |
| # Send to TDLib | |
| movq client_handle(%rip), %rdi | |
| movq $json_buffer, %rsi | |
| movq send_func(%rip), %rax | |
| call *%rax | |
| movq $0, auth_state(%rip) | |
| movq $10000, %rdi | |
| call usleep | |
| jmp .auth_loop | |
| .request_code: | |
| movq $code_prompt, %rdi | |
| call printf | |
| xorq %rdi, %rdi | |
| call fflush | |
| # Read code | |
| movq $code_buffer, %rdi | |
| movq $16, %rsi | |
| movq stdin(%rip), %rdx | |
| call fgets | |
| testq %rax, %rax | |
| jz .input_error | |
| # Remove newline | |
| movq $code_buffer, %rdi | |
| call remove_newline | |
| # Create JSON for code | |
| movq $json_buffer, %rdi | |
| movq $fmt_code, %rsi | |
| movq $code_buffer, %rdx | |
| call sprintf | |
| # Send to TDLib | |
| movq client_handle(%rip), %rdi | |
| movq $json_buffer, %rsi | |
| movq send_func(%rip), %rax | |
| call *%rax | |
| movq $0, auth_state(%rip) | |
| movq $10000, %rdi | |
| call usleep | |
| jmp .auth_loop | |
| .request_password: | |
| movq $password_prompt, %rdi | |
| call printf | |
| xorq %rdi, %rdi | |
| call fflush | |
| # Read password | |
| movq $password_buffer, %rdi | |
| movq $64, %rsi | |
| movq stdin(%rip), %rdx | |
| call fgets | |
| testq %rax, %rax | |
| jz .input_error | |
| # Remove newline | |
| movq $password_buffer, %rdi | |
| call remove_newline | |
| # Create JSON for password | |
| movq $json_buffer, %rdi | |
| movq $fmt_password, %rsi | |
| movq $password_buffer, %rdx | |
| call sprintf | |
| # Send to TDLib | |
| movq client_handle(%rip), %rdi | |
| movq $json_buffer, %rsi | |
| movq send_func(%rip), %rax | |
| call *%rax | |
| movq $0, auth_state(%rip) | |
| movq $10000, %rdi | |
| call usleep | |
| jmp .auth_loop | |
| .auth_complete: | |
| movq $auth_success, %rdi | |
| call printf | |
| # Main loop | |
| movq $100, %r13 | |
| .main_loop: | |
| # Receive messages | |
| movq client_handle(%rip), %rdi | |
| xorq %rsi, %rsi | |
| movq receive_func(%rip), %rax | |
| call *%rax | |
| testq %rax, %rax | |
| jz .no_msg_main | |
| # Print message | |
| movq %rax, %rdi | |
| call printf | |
| movq $newline, %rdi | |
| call printf | |
| .no_msg_main: | |
| movq $50000, %rdi | |
| call usleep | |
| decq %r13 | |
| jnz .main_loop | |
| .cleanup: | |
| # Send close command | |
| movq client_handle(%rip), %rdi | |
| movq $close_msg, %rsi | |
| movq send_func(%rip), %rax | |
| call *%rax | |
| movq $50000, %rdi | |
| call usleep | |
| # Destroy client | |
| movq client_handle(%rip), %rdi | |
| movq destroy_func(%rip), %rax | |
| call *%rax | |
| # Exit | |
| xorq %rdi, %rdi | |
| call exit | |
| .dl_error: | |
| movq $lib_error, %rdi | |
| call printf | |
| movq $1, %rdi | |
| call exit | |
| .client_error: | |
| movq $client_error, %rdi | |
| call printf | |
| jmp .cleanup | |
| .input_error: | |
| movq $input_error, %rdi | |
| call printf | |
| jmp .cleanup | |
| process_message: | |
| pushq %rbp | |
| movq %rsp, %rbp | |
| pushq %r12 | |
| pushq %r13 | |
| movq %rdi, %r12 | |
| movq %r12, %rdi | |
| movq $auth_wait_phone, %rsi | |
| call strstr | |
| testq %rax, %rax | |
| jnz .wait_phone | |
| movq %r12, %rdi | |
| movq $auth_wait_code, %rsi | |
| call strstr | |
| testq %rax, %rax | |
| jnz .wait_code | |
| movq %r12, %rdi | |
| movq $auth_wait_password, %rsi | |
| call strstr | |
| testq %rax, %rax | |
| jnz .wait_password | |
| movq %r12, %rdi | |
| movq $auth_ready, %rsi | |
| call strstr | |
| testq %rax, %rax | |
| jnz .auth_ready_done | |
| jmp .done | |
| .wait_phone: | |
| movq $1, auth_state(%rip) | |
| jmp .done | |
| .wait_code: | |
| movq $2, auth_state(%rip) | |
| jmp .done | |
| .wait_password: | |
| movq $3, auth_state(%rip) | |
| jmp .done | |
| .auth_ready_done: | |
| movq $1, %r12 | |
| movq $0, auth_state(%rip) | |
| .done: | |
| popq %r13 | |
| popq %r12 | |
| popq %rbp | |
| ret | |
| remove_newline: | |
| pushq %rbp | |
| movq %rsp, %rbp | |
| movq %rdi, %rcx | |
| .find_end: | |
| cmpb $0, (%rcx) | |
| je .check_newline | |
| incq %rcx | |
| jmp .find_end | |
| .check_newline: | |
| decq %rcx | |
| cmpb $10, (%rcx) | |
| jne .end | |
| movb $0, (%rcx) | |
| .end: | |
| popq %rbp | |
| ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment