asm {
PUT_DEC_U64::
//RAX is number to print in decimal.
//Preserves all regs.
PUSH RBP
MOV RBP,RSP
SUB RSP,24 //24 char buffer on stack

//Save regs which C code is free to clobber. We don't have to for C callers,
//but this function will be nice for ASM callers if it saves all regs.
PUSH_C_REGS

PUSH RSI //See REGG_LOCAL_VARS&REGG_LOCAL_NON_PTR_VARS
LEA RSI,-1[RBP] //Load addr of end of buffer.
//We picked RSI because of PUT_STR
//We'll move bwd
MOV U8 [RSI],0 //Terminator

TEST RAX,RAX //Special case -- zero
JNZ @@05
DEC RSI
MOV U8 [RSI],'0'
JMP @@15

@@05: MOV RBX,10 //Divides by 10

@@10: XOR RDX,RDX
DIV RBX //RAX=(RDX:RAX)/RBX with remainder in RDX
ADD RDX,'0'
DEC RSI
MOV U8 [RSI],DL
TEST RAX,RAX
JNZ @@10

@@15: CALL PUT_STR
POP RSI
POP_C_REGS
LEAVE
RET

_DO_IT:: //The convention is C-callable routines have underscores.
MOV RAX,122333221
CALL PUT_DEC_U64
MOV RAX,'\n'
CALL PUT_CHARS
RET
}

Call(_DO_IT);