我在EDX中存储了大的64位数:EAX分别为21C3677C:82B40000。我试图将数字作为小数打印到控制台2432902008176640000是否有系统调用可以让我完成此操作?
答案 0 :(得分:1)
有人必须怜悯这个家伙和他的同学。如果“只是打电话给printf”没有作弊,使用它也不应该作弊。我从我遇到的第一个asm程序中偷走了这个。它使用DOS中断来查找磁盘大小,并使用逗号每三位数打印dx:ax
。你们可能不需要逗号。我已经修了多年 - 可能很快会做rdx:rax
版本。非常适合显示阶乘。这是非常天真和低效,但仍然有效。随意改进它。当你在缓冲区中获得了字符之后,当然,这只是“Hello World”和不同的歌词。
;-----------------------------------------------
; u64toda - converts (64 bit) integer in edx:eax
; to (comma delimited) decimal representation in
; zero (was "$") terminated string in buffer pointed to by edi
;----------------------------------------
u64toda:
pusha
mov ebx, edx ; stash high dword
mov esi,0Ah ; prepare to divide by 10
xor ecx, ecx ; zero the digit count
jmp highleft ; check is high word 0 ?
highword:
xchg eax,ebx ; swap high & low words
xor edx,edx ; zero edx for the divide!
div esi ; divide high word by 10
xchg eax,ebx ; swap 'em back
div esi ; divide low word including remainder
push edx ; remainder is our digit - save it
inc ecx ; count digits
highleft:
or ebx,ebx
jnz highword
lowleft:
xor edx,edx ; zero high word
div esi ; divide low word by 10
push edx ; our digit
inc ecx ; count it
or eax,eax ; 0 yet ?
jne lowleft
cmp ecx, byte 4 ; commas needed ?
jl write2buf ; nope
xor edx,edx ; zero high word for divide
mov eax,ecx ; number of digits
mov ebx,3
div ebx
mov esi,edx ; remainder = number digits before comma
test edx,edx
jnz write2buf ; no remainder?
mov esi,3 ; we can write 3 digits, then.
write2buf:
pop eax ; get digit back - in right order
add al,30H ; convert to ascii character
stosb ; write it to our buffer
dec esi ; digits before comma needed
jnz moredigits ; no comma needed yet
cmp ecx,2 ; we at the end?
jl moredigits ; don't need comma
mov al,',' ; write a comma
stosb
mov esi,03h ; we're good for another 3 digits
moredigits:
loop write2buf ; write more digits - cx of 'em
mov al,00h ; terminate buffer with zero
stosb
popa
ret
;------------------------
答案 1 :(得分:0)
哪个操作系统?在Linux上,您使用write
系统调用。这是通过您正在使用的语言的标准库完成的事情。您必须自己完成从二进制到十进制ASCII字符的转换,然后将write
系统调用指向该ASCII文本,给它长度,并告诉它要写入哪个文件描述符,stdout将是文件描述符1
。
这是查找Linux中使用的系统调用的一种方法。编写一个简单的程序并在strace
下调用它,它将跟踪程序所做的所有系统调用。
例如,我编写了这个C ++程序
#include <iostream>
int main( int argc, char* argv[] )
{
static volatile unsigned long long x = 0x21C3677C82B40000;
std::cout << x << std::endl;
return 0;
}
编译如下:
g++ -O3 main.cpp -o main
然后使用strace
将stderr重定向到文件main.trace
$ strace -y ./main 2> main.trace
2432902008176640000
$
它写了你想要的十进制数。通过grep&#34; dev&#34;来查找设备的I / O.在追踪
$ grep dev main.trace
fstat(1</dev/pts/3>, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
write(1</dev/pts/3>, "2432902008176640000\n", 20) = 20
$
您会注意到C ++标准库对与fstat
(1)关联的文件描述符执行了stdout
,然后进行了write
系统调用,并指向了数据2432902008176640000\n
和长度20
。
答案 2 :(得分:0)
以下是如何使用printf打印64位数字的示例。此代码适用于YASM。
segment .data
format db "Number %ld", 0x0a, 0 ; Format string for printf
result dq 0 ; Quad word to store the EDX:EAX result in
segment .text
global main
extern printf
main:
; Store the 64 bit number in the quad word "result"
mov edx, 0x21C3677C ; Store the EDX value
mov eax, 0x82B40000 ; Store the EAX value
mov [result], eax ; Lower half of "result" will be EAX
mov [result+4], edx ; Upper half of "result" will be EDX
; Print "result" with the printf function
xor eax, eax ; No float parameters for printf
lea rdi, [format] ; First parameter for printf (format string)
mov rsi, [result] ; Second parameter for printf ("result")
call printf ; Call printf
; End program
xor eax, eax ; Return 0
ret
使用以下命令构建二进制文件:
yasm -f elf64 example.asm
gcc -o example example.o
更新:不使用内存的示例
segment .data
format db "Number %ld", 0x0a, 0 ; Format string for printf
segment .text
global main
extern printf
main:
; Store the 64 bit number in register rsi
mov edx, 0x21C3677C ; Store the EDX value (upper half)
mov eax, 0x82B40000 ; Store the EAX value (lower half)
mov esi, edx ; Place upper half in esi
shl rsi, 32 ; Shift left 32 bits
or rsi, rax ; Place the lower half in rsi
; Print "result" with the printf function
xor eax, eax ; No float parameters for printf
lea rdi, [format] ; First parameter for printf (format string)
call printf ; Call printf
; End program
xor eax, eax ; Return 0
ret