How to get length of long strings in x86 assembly to print on assertion The 2019 Stack Overflow Developer Survey Results Are InNASM - Macro local label as parameter to another macroHow to print signed integer in x86 assembly (NASM) on MacHow to determine if a .NET assembly was built for x86 or x64?How do I use Assert to verify that an exception has been thrown?How do I generate a stream from a string?NASM x86_64 having trouble writing command line arguments, returning -14 in raxPrint number on screen in x86-64 assemblerGeneral structure for executing system commands from x86-64 assembly (NASM)?How to get this simple assembly to run?Assembly print variables and valuesHow to print the length of a string in assemblyAvoiding the JMP in the JMP CALL POP technique for shellcode NASM?

Time travel alters history but people keep saying nothing's changed

Can you compress metal and what would be the consequences?

Did 3000BC Egyptians use meteoric iron weapons?

Is an up-to-date browser secure on an out-of-date OS?

Is this app Icon Browser Safe/Legit?

What is the most effective way of iterating a std::vector and why?

For what reasons would an animal species NOT cross a *horizontal* land bridge?

How to save as into a customized destination on macOS?

Where to refill my bottle in India?

Do these rules for Critical Successes and Critical Failures seem fair?

FPGA - DIY Programming

Why can Shazam fly?

Pokemon Turn Based battle (Python)

A poker game description that does not feel gimmicky

Why hard-Brexiteers don't insist on a hard border to prevent illegal immigration after Brexit?

Should I use my personal e-mail address, or my workplace one, when registering to external websites for work purposes?

Shouldn't "much" here be used instead of "more"?

Why didn't the Event Horizon Telescope team mention Sagittarius A*?

"as much details as you can remember"

Why did Acorn's A3000 have red function keys?

Origin of "cooter" meaning "vagina"

What is the closest word meaning "respect for time / mindful"

Is there a symbol for a right arrow with a square in the middle?

What do hard-Brexiteers want with respect to the Irish border?



How to get length of long strings in x86 assembly to print on assertion



The 2019 Stack Overflow Developer Survey Results Are InNASM - Macro local label as parameter to another macroHow to print signed integer in x86 assembly (NASM) on MacHow to determine if a .NET assembly was built for x86 or x64?How do I use Assert to verify that an exception has been thrown?How do I generate a stream from a string?NASM x86_64 having trouble writing command line arguments, returning -14 in raxPrint number on screen in x86-64 assemblerGeneral structure for executing system commands from x86-64 assembly (NASM)?How to get this simple assembly to run?Assembly print variables and valuesHow to print the length of a string in assemblyAvoiding the JMP in the JMP CALL POP technique for shellcode NASM?



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








1















I am trying to build an x86 program that reads a file into memory. It uses a few different syscalls, and messes with memory and such. There's a lot in there to figure out.



To simplify debugging and figuring this out, I wanted to add assert statements which, if there's a mismatch, it prints out a nice error message. This is the first step in learning assembly so I can print the numbers and strings that get placed on different registers and such after operations. Then I can print them out and debug them without any fancy tools.



Wondering if one could help me write an ASSERT AND PRINT in NASM for Mac x86-64. I have this so far:



%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax

%define EXIT 0x2000001
%define EXIT_STATUS 0

%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)

%define PROT_NONE 0x00 ; no permissions
%define PROT_READ 0x01 ; pages can be read
%define PROT_WRITE 0x02 ; pages can be written
%define PROT_EXEC 0x04 ; pages can be executed

%define MAP_SHARED 0x0001 ; share changes
%define MAP_PRIVATE 0x0002 ; changes are private
%define MAP_FIXED 0x0010 ; map addr must be exactly as requested
%define MAP_RENAME 0x0020 ; Sun: rename private pages to file
%define MAP_NORESERVE 0x0040 ; Sun: don't reserve needed swap area
%define MAP_INHERIT 0x0080 ; region is retained after exec
%define MAP_NOEXTEND 0x0100 ; for MAP_FILE, don't change file size
%define MAP_HASSEMAPHORE 0x0200 ; region may contain semaphores

;
; Assert equals.
;

%macro ASSERT 3
cmp %1, %2
jne prepare_error
prepare_error:
push %3
jmp throw_error
%endmacro

;
; Print to stdout.
;

%macro PRINT 1
mov c, getLengthOf(%1) ; "rdx" stores the string length
mov b, %1 ; "rsi" stores the byte string to be used
mov a, 1 ; "rdi" tells where to write (stdout file descriptor: 1)
mov i, WRITE ; syscall: write
syscall
%endmacro

;
; Read file into memory.
;

start:
ASSERT PROT_READ, 0x01, "Something wrong with PROT_READ"

mov b, PROT_READ
mov a, PROT_WRITE
xor a, b

mov f, 0
mov e, -1
mov d, MAP_PRIVATE
mov c, a
mov b, 500000
mov a, 0
mov i, MMAP
syscall
PRINT "mmap output "
PRINT i ; check what's returned
PRINT "n"
mov e, i

mov b, O_RDONLY
mov a, "Makefile"
mov i, OPEN
syscall
mov a, i

mov b, e
mov i, READ
syscall

;
; Exit status
;

exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; syscall: exit
syscall

throw_error:
PRINT pop() ; print error or something
jmp exit









share|improve this question

















  • 1





    github.com/cirosantilli/x86-assembly-cheat/blob/…

    – Lance Pollard
    Mar 22 at 11:57

















1















I am trying to build an x86 program that reads a file into memory. It uses a few different syscalls, and messes with memory and such. There's a lot in there to figure out.



To simplify debugging and figuring this out, I wanted to add assert statements which, if there's a mismatch, it prints out a nice error message. This is the first step in learning assembly so I can print the numbers and strings that get placed on different registers and such after operations. Then I can print them out and debug them without any fancy tools.



Wondering if one could help me write an ASSERT AND PRINT in NASM for Mac x86-64. I have this so far:



%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax

%define EXIT 0x2000001
%define EXIT_STATUS 0

%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)

%define PROT_NONE 0x00 ; no permissions
%define PROT_READ 0x01 ; pages can be read
%define PROT_WRITE 0x02 ; pages can be written
%define PROT_EXEC 0x04 ; pages can be executed

%define MAP_SHARED 0x0001 ; share changes
%define MAP_PRIVATE 0x0002 ; changes are private
%define MAP_FIXED 0x0010 ; map addr must be exactly as requested
%define MAP_RENAME 0x0020 ; Sun: rename private pages to file
%define MAP_NORESERVE 0x0040 ; Sun: don't reserve needed swap area
%define MAP_INHERIT 0x0080 ; region is retained after exec
%define MAP_NOEXTEND 0x0100 ; for MAP_FILE, don't change file size
%define MAP_HASSEMAPHORE 0x0200 ; region may contain semaphores

;
; Assert equals.
;

%macro ASSERT 3
cmp %1, %2
jne prepare_error
prepare_error:
push %3
jmp throw_error
%endmacro

;
; Print to stdout.
;

%macro PRINT 1
mov c, getLengthOf(%1) ; "rdx" stores the string length
mov b, %1 ; "rsi" stores the byte string to be used
mov a, 1 ; "rdi" tells where to write (stdout file descriptor: 1)
mov i, WRITE ; syscall: write
syscall
%endmacro

;
; Read file into memory.
;

start:
ASSERT PROT_READ, 0x01, "Something wrong with PROT_READ"

mov b, PROT_READ
mov a, PROT_WRITE
xor a, b

mov f, 0
mov e, -1
mov d, MAP_PRIVATE
mov c, a
mov b, 500000
mov a, 0
mov i, MMAP
syscall
PRINT "mmap output "
PRINT i ; check what's returned
PRINT "n"
mov e, i

mov b, O_RDONLY
mov a, "Makefile"
mov i, OPEN
syscall
mov a, i

mov b, e
mov i, READ
syscall

;
; Exit status
;

exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; syscall: exit
syscall

throw_error:
PRINT pop() ; print error or something
jmp exit









share|improve this question

















  • 1





    github.com/cirosantilli/x86-assembly-cheat/blob/…

    – Lance Pollard
    Mar 22 at 11:57













1












1








1








I am trying to build an x86 program that reads a file into memory. It uses a few different syscalls, and messes with memory and such. There's a lot in there to figure out.



To simplify debugging and figuring this out, I wanted to add assert statements which, if there's a mismatch, it prints out a nice error message. This is the first step in learning assembly so I can print the numbers and strings that get placed on different registers and such after operations. Then I can print them out and debug them without any fancy tools.



Wondering if one could help me write an ASSERT AND PRINT in NASM for Mac x86-64. I have this so far:



%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax

%define EXIT 0x2000001
%define EXIT_STATUS 0

%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)

%define PROT_NONE 0x00 ; no permissions
%define PROT_READ 0x01 ; pages can be read
%define PROT_WRITE 0x02 ; pages can be written
%define PROT_EXEC 0x04 ; pages can be executed

%define MAP_SHARED 0x0001 ; share changes
%define MAP_PRIVATE 0x0002 ; changes are private
%define MAP_FIXED 0x0010 ; map addr must be exactly as requested
%define MAP_RENAME 0x0020 ; Sun: rename private pages to file
%define MAP_NORESERVE 0x0040 ; Sun: don't reserve needed swap area
%define MAP_INHERIT 0x0080 ; region is retained after exec
%define MAP_NOEXTEND 0x0100 ; for MAP_FILE, don't change file size
%define MAP_HASSEMAPHORE 0x0200 ; region may contain semaphores

;
; Assert equals.
;

%macro ASSERT 3
cmp %1, %2
jne prepare_error
prepare_error:
push %3
jmp throw_error
%endmacro

;
; Print to stdout.
;

%macro PRINT 1
mov c, getLengthOf(%1) ; "rdx" stores the string length
mov b, %1 ; "rsi" stores the byte string to be used
mov a, 1 ; "rdi" tells where to write (stdout file descriptor: 1)
mov i, WRITE ; syscall: write
syscall
%endmacro

;
; Read file into memory.
;

start:
ASSERT PROT_READ, 0x01, "Something wrong with PROT_READ"

mov b, PROT_READ
mov a, PROT_WRITE
xor a, b

mov f, 0
mov e, -1
mov d, MAP_PRIVATE
mov c, a
mov b, 500000
mov a, 0
mov i, MMAP
syscall
PRINT "mmap output "
PRINT i ; check what's returned
PRINT "n"
mov e, i

mov b, O_RDONLY
mov a, "Makefile"
mov i, OPEN
syscall
mov a, i

mov b, e
mov i, READ
syscall

;
; Exit status
;

exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; syscall: exit
syscall

throw_error:
PRINT pop() ; print error or something
jmp exit









share|improve this question














I am trying to build an x86 program that reads a file into memory. It uses a few different syscalls, and messes with memory and such. There's a lot in there to figure out.



To simplify debugging and figuring this out, I wanted to add assert statements which, if there's a mismatch, it prints out a nice error message. This is the first step in learning assembly so I can print the numbers and strings that get placed on different registers and such after operations. Then I can print them out and debug them without any fancy tools.



Wondering if one could help me write an ASSERT AND PRINT in NASM for Mac x86-64. I have this so far:



%define a rdi
%define b rsi
%define c rdx
%define d r10
%define e r8
%define f r9
%define i rax

%define EXIT 0x2000001
%define EXIT_STATUS 0

%define READ 0x2000003 ; read
%define WRITE 0x2000004 ; write
%define OPEN 0x2000005 ; open(path, oflag)
%define CLOSE 0x2000006 ; CLOSE
%define MMAP 0x2000197 ; mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset)

%define PROT_NONE 0x00 ; no permissions
%define PROT_READ 0x01 ; pages can be read
%define PROT_WRITE 0x02 ; pages can be written
%define PROT_EXEC 0x04 ; pages can be executed

%define MAP_SHARED 0x0001 ; share changes
%define MAP_PRIVATE 0x0002 ; changes are private
%define MAP_FIXED 0x0010 ; map addr must be exactly as requested
%define MAP_RENAME 0x0020 ; Sun: rename private pages to file
%define MAP_NORESERVE 0x0040 ; Sun: don't reserve needed swap area
%define MAP_INHERIT 0x0080 ; region is retained after exec
%define MAP_NOEXTEND 0x0100 ; for MAP_FILE, don't change file size
%define MAP_HASSEMAPHORE 0x0200 ; region may contain semaphores

;
; Assert equals.
;

%macro ASSERT 3
cmp %1, %2
jne prepare_error
prepare_error:
push %3
jmp throw_error
%endmacro

;
; Print to stdout.
;

%macro PRINT 1
mov c, getLengthOf(%1) ; "rdx" stores the string length
mov b, %1 ; "rsi" stores the byte string to be used
mov a, 1 ; "rdi" tells where to write (stdout file descriptor: 1)
mov i, WRITE ; syscall: write
syscall
%endmacro

;
; Read file into memory.
;

start:
ASSERT PROT_READ, 0x01, "Something wrong with PROT_READ"

mov b, PROT_READ
mov a, PROT_WRITE
xor a, b

mov f, 0
mov e, -1
mov d, MAP_PRIVATE
mov c, a
mov b, 500000
mov a, 0
mov i, MMAP
syscall
PRINT "mmap output "
PRINT i ; check what's returned
PRINT "n"
mov e, i

mov b, O_RDONLY
mov a, "Makefile"
mov i, OPEN
syscall
mov a, i

mov b, e
mov i, READ
syscall

;
; Exit status
;

exit:
mov a, EXIT_STATUS ; exit status
mov i, EXIT ; syscall: exit
syscall

throw_error:
PRINT pop() ; print error or something
jmp exit






macos unit-testing assembly x86-64 nasm






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 22 at 3:44









Lance PollardLance Pollard

32.1k68206350




32.1k68206350







  • 1





    github.com/cirosantilli/x86-assembly-cheat/blob/…

    – Lance Pollard
    Mar 22 at 11:57












  • 1





    github.com/cirosantilli/x86-assembly-cheat/blob/…

    – Lance Pollard
    Mar 22 at 11:57







1




1





github.com/cirosantilli/x86-assembly-cheat/blob/…

– Lance Pollard
Mar 22 at 11:57





github.com/cirosantilli/x86-assembly-cheat/blob/…

– Lance Pollard
Mar 22 at 11:57












1 Answer
1






active

oldest

votes


















2














mov rsi, "abcdefgh" is a mov-immediate of the string contents, not a pointer to it. It only exists as an immediate if you do that.



Your macro will need to switch to .rodata and back to put the string in memory; possibly you could turn it into a sequence of push-immediate onto the stack with NASM macros, but that sounds hard.



So you can use the usual msglen equ $ - msg to get the length. (Actually using NASM local labels so the macro doesn't create conflicts).




See NASM - Macro local label as parameter to another macro where I wrote basically this answer a couple weeks ago. But not exactly a duplicate because it didn't have the bug of using the string as an immediate.



Anyway, NASM has no support AFAIK for switching sections and then coming back to the current section, like GAS .pushsection. So we're stuck hard-coding section .text unless you want to add an optional parameter for section name.



 ; write(1, string, sizeof(stringarray))
; switches to SECTION .text regardless of previous section
; clobbers: RDI, RSI, RDX, RCX,R11 (by syscall itself)
: output: RAX = bytes written, or -errno
%macro PRINT 1
section .rodata
;; NASM macro-local labels
%%str db %1 ; put the string in read-only memory
%%strln equ $ - %%str ; current position - string start
section .text
mov edx, %%strlen ; len
lea rsi, [rel %%str] ; buf = the string. (RIP-relative for position-independent)
mov edi, 1 ; fd = stdout
mov eax, WRITE
syscall
%endmacro


This doesn't attempt to combine duplicates of the same string. Using it many times with the same message will be inefficient. This doesn't matter for debugging.



I could have left your %defines for RDI, and let NASM optimize mov rdi, 1 (7 bytes) into mov edi, 1 (5 bytes). But YASM won't do that so it's better to make it explicit if you care about anyone building your code with YASM.



I used a RIP-relative LEA because that's the most efficient way to put a static address into a register in position-independent code. In Linux non-PIE executables, use mov esi, %%str (5 bytes and can run on any port, more than LEA). But on OS X, the base virtual address where an executable is mapped/loaded is always above 2^32, and you never want mov r64, imm64 with a 64-bit absolute address.




On Linux, where system-call numbers are small integers, you could use lea eax, [rdi-1 + WRITE] to do eax = SYS_write with a 3 byte instruction vs. 5 for mov.






share|improve this answer




















  • 1





    One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

    – Kamil.S
    Mar 25 at 11:54












  • @Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

    – Peter Cordes
    Mar 25 at 19:15






  • 1





    Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

    – Kamil.S
    Mar 25 at 20:38











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55292583%2fhow-to-get-length-of-long-strings-in-x86-assembly-to-print-on-assertion%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














mov rsi, "abcdefgh" is a mov-immediate of the string contents, not a pointer to it. It only exists as an immediate if you do that.



Your macro will need to switch to .rodata and back to put the string in memory; possibly you could turn it into a sequence of push-immediate onto the stack with NASM macros, but that sounds hard.



So you can use the usual msglen equ $ - msg to get the length. (Actually using NASM local labels so the macro doesn't create conflicts).




See NASM - Macro local label as parameter to another macro where I wrote basically this answer a couple weeks ago. But not exactly a duplicate because it didn't have the bug of using the string as an immediate.



Anyway, NASM has no support AFAIK for switching sections and then coming back to the current section, like GAS .pushsection. So we're stuck hard-coding section .text unless you want to add an optional parameter for section name.



 ; write(1, string, sizeof(stringarray))
; switches to SECTION .text regardless of previous section
; clobbers: RDI, RSI, RDX, RCX,R11 (by syscall itself)
: output: RAX = bytes written, or -errno
%macro PRINT 1
section .rodata
;; NASM macro-local labels
%%str db %1 ; put the string in read-only memory
%%strln equ $ - %%str ; current position - string start
section .text
mov edx, %%strlen ; len
lea rsi, [rel %%str] ; buf = the string. (RIP-relative for position-independent)
mov edi, 1 ; fd = stdout
mov eax, WRITE
syscall
%endmacro


This doesn't attempt to combine duplicates of the same string. Using it many times with the same message will be inefficient. This doesn't matter for debugging.



I could have left your %defines for RDI, and let NASM optimize mov rdi, 1 (7 bytes) into mov edi, 1 (5 bytes). But YASM won't do that so it's better to make it explicit if you care about anyone building your code with YASM.



I used a RIP-relative LEA because that's the most efficient way to put a static address into a register in position-independent code. In Linux non-PIE executables, use mov esi, %%str (5 bytes and can run on any port, more than LEA). But on OS X, the base virtual address where an executable is mapped/loaded is always above 2^32, and you never want mov r64, imm64 with a 64-bit absolute address.




On Linux, where system-call numbers are small integers, you could use lea eax, [rdi-1 + WRITE] to do eax = SYS_write with a 3 byte instruction vs. 5 for mov.






share|improve this answer




















  • 1





    One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

    – Kamil.S
    Mar 25 at 11:54












  • @Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

    – Peter Cordes
    Mar 25 at 19:15






  • 1





    Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

    – Kamil.S
    Mar 25 at 20:38















2














mov rsi, "abcdefgh" is a mov-immediate of the string contents, not a pointer to it. It only exists as an immediate if you do that.



Your macro will need to switch to .rodata and back to put the string in memory; possibly you could turn it into a sequence of push-immediate onto the stack with NASM macros, but that sounds hard.



So you can use the usual msglen equ $ - msg to get the length. (Actually using NASM local labels so the macro doesn't create conflicts).




See NASM - Macro local label as parameter to another macro where I wrote basically this answer a couple weeks ago. But not exactly a duplicate because it didn't have the bug of using the string as an immediate.



Anyway, NASM has no support AFAIK for switching sections and then coming back to the current section, like GAS .pushsection. So we're stuck hard-coding section .text unless you want to add an optional parameter for section name.



 ; write(1, string, sizeof(stringarray))
; switches to SECTION .text regardless of previous section
; clobbers: RDI, RSI, RDX, RCX,R11 (by syscall itself)
: output: RAX = bytes written, or -errno
%macro PRINT 1
section .rodata
;; NASM macro-local labels
%%str db %1 ; put the string in read-only memory
%%strln equ $ - %%str ; current position - string start
section .text
mov edx, %%strlen ; len
lea rsi, [rel %%str] ; buf = the string. (RIP-relative for position-independent)
mov edi, 1 ; fd = stdout
mov eax, WRITE
syscall
%endmacro


This doesn't attempt to combine duplicates of the same string. Using it many times with the same message will be inefficient. This doesn't matter for debugging.



I could have left your %defines for RDI, and let NASM optimize mov rdi, 1 (7 bytes) into mov edi, 1 (5 bytes). But YASM won't do that so it's better to make it explicit if you care about anyone building your code with YASM.



I used a RIP-relative LEA because that's the most efficient way to put a static address into a register in position-independent code. In Linux non-PIE executables, use mov esi, %%str (5 bytes and can run on any port, more than LEA). But on OS X, the base virtual address where an executable is mapped/loaded is always above 2^32, and you never want mov r64, imm64 with a 64-bit absolute address.




On Linux, where system-call numbers are small integers, you could use lea eax, [rdi-1 + WRITE] to do eax = SYS_write with a 3 byte instruction vs. 5 for mov.






share|improve this answer




















  • 1





    One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

    – Kamil.S
    Mar 25 at 11:54












  • @Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

    – Peter Cordes
    Mar 25 at 19:15






  • 1





    Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

    – Kamil.S
    Mar 25 at 20:38













2












2








2







mov rsi, "abcdefgh" is a mov-immediate of the string contents, not a pointer to it. It only exists as an immediate if you do that.



Your macro will need to switch to .rodata and back to put the string in memory; possibly you could turn it into a sequence of push-immediate onto the stack with NASM macros, but that sounds hard.



So you can use the usual msglen equ $ - msg to get the length. (Actually using NASM local labels so the macro doesn't create conflicts).




See NASM - Macro local label as parameter to another macro where I wrote basically this answer a couple weeks ago. But not exactly a duplicate because it didn't have the bug of using the string as an immediate.



Anyway, NASM has no support AFAIK for switching sections and then coming back to the current section, like GAS .pushsection. So we're stuck hard-coding section .text unless you want to add an optional parameter for section name.



 ; write(1, string, sizeof(stringarray))
; switches to SECTION .text regardless of previous section
; clobbers: RDI, RSI, RDX, RCX,R11 (by syscall itself)
: output: RAX = bytes written, or -errno
%macro PRINT 1
section .rodata
;; NASM macro-local labels
%%str db %1 ; put the string in read-only memory
%%strln equ $ - %%str ; current position - string start
section .text
mov edx, %%strlen ; len
lea rsi, [rel %%str] ; buf = the string. (RIP-relative for position-independent)
mov edi, 1 ; fd = stdout
mov eax, WRITE
syscall
%endmacro


This doesn't attempt to combine duplicates of the same string. Using it many times with the same message will be inefficient. This doesn't matter for debugging.



I could have left your %defines for RDI, and let NASM optimize mov rdi, 1 (7 bytes) into mov edi, 1 (5 bytes). But YASM won't do that so it's better to make it explicit if you care about anyone building your code with YASM.



I used a RIP-relative LEA because that's the most efficient way to put a static address into a register in position-independent code. In Linux non-PIE executables, use mov esi, %%str (5 bytes and can run on any port, more than LEA). But on OS X, the base virtual address where an executable is mapped/loaded is always above 2^32, and you never want mov r64, imm64 with a 64-bit absolute address.




On Linux, where system-call numbers are small integers, you could use lea eax, [rdi-1 + WRITE] to do eax = SYS_write with a 3 byte instruction vs. 5 for mov.






share|improve this answer















mov rsi, "abcdefgh" is a mov-immediate of the string contents, not a pointer to it. It only exists as an immediate if you do that.



Your macro will need to switch to .rodata and back to put the string in memory; possibly you could turn it into a sequence of push-immediate onto the stack with NASM macros, but that sounds hard.



So you can use the usual msglen equ $ - msg to get the length. (Actually using NASM local labels so the macro doesn't create conflicts).




See NASM - Macro local label as parameter to another macro where I wrote basically this answer a couple weeks ago. But not exactly a duplicate because it didn't have the bug of using the string as an immediate.



Anyway, NASM has no support AFAIK for switching sections and then coming back to the current section, like GAS .pushsection. So we're stuck hard-coding section .text unless you want to add an optional parameter for section name.



 ; write(1, string, sizeof(stringarray))
; switches to SECTION .text regardless of previous section
; clobbers: RDI, RSI, RDX, RCX,R11 (by syscall itself)
: output: RAX = bytes written, or -errno
%macro PRINT 1
section .rodata
;; NASM macro-local labels
%%str db %1 ; put the string in read-only memory
%%strln equ $ - %%str ; current position - string start
section .text
mov edx, %%strlen ; len
lea rsi, [rel %%str] ; buf = the string. (RIP-relative for position-independent)
mov edi, 1 ; fd = stdout
mov eax, WRITE
syscall
%endmacro


This doesn't attempt to combine duplicates of the same string. Using it many times with the same message will be inefficient. This doesn't matter for debugging.



I could have left your %defines for RDI, and let NASM optimize mov rdi, 1 (7 bytes) into mov edi, 1 (5 bytes). But YASM won't do that so it's better to make it explicit if you care about anyone building your code with YASM.



I used a RIP-relative LEA because that's the most efficient way to put a static address into a register in position-independent code. In Linux non-PIE executables, use mov esi, %%str (5 bytes and can run on any port, more than LEA). But on OS X, the base virtual address where an executable is mapped/loaded is always above 2^32, and you never want mov r64, imm64 with a 64-bit absolute address.




On Linux, where system-call numbers are small integers, you could use lea eax, [rdi-1 + WRITE] to do eax = SYS_write with a 3 byte instruction vs. 5 for mov.







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 22 at 6:19

























answered Mar 22 at 5:38









Peter CordesPeter Cordes

135k19204344




135k19204344







  • 1





    One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

    – Kamil.S
    Mar 25 at 11:54












  • @Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

    – Peter Cordes
    Mar 25 at 19:15






  • 1





    Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

    – Kamil.S
    Mar 25 at 20:38












  • 1





    One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

    – Kamil.S
    Mar 25 at 11:54












  • @Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

    – Peter Cordes
    Mar 25 at 19:15






  • 1





    Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

    – Kamil.S
    Mar 25 at 20:38







1




1





One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

– Kamil.S
Mar 25 at 11:54






One remark it's possible to manually craft a MacOS (including latest Mojave 10.13.x) 64bit executable with base virtual address 0x1000 (not lower though). That's not something ld would ever do though.

– Kamil.S
Mar 25 at 11:54














@Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

– Peter Cordes
Mar 25 at 19:15





@Kamil.S: Neat. Do executable still need to be relocatable for ASLR? Or could you then (in theory) make position-dependent code that uses 32-bit absolute addresses? IIRC, MachO64 object files don't support 32-bit relocations, so the "linker" inputs might need to be ELF64, or flat binaries you made with org 0x1000

– Peter Cordes
Mar 25 at 19:15




1




1





Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

– Kamil.S
Mar 25 at 20:38





Yes, executable does need the MH_PIE flag to allow ASLR. Position-dependent code will happily accept 32-bit absolute addresses and it does work. I don't use MachO64 object files in this setup just raw binary format and hand crafted Mach-O header , so I can't really tell on the former.

– Kamil.S
Mar 25 at 20:38



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55292583%2fhow-to-get-length-of-long-strings-in-x86-assembly-to-print-on-assertion%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript