0

I'm trying to print single character on the screen using assembly inserts with this code:

char z[]="x";
int result;

asm( "mov 4, %%eax" : );
asm( "mov 1, %%ebx" : );
asm( "mov %%edx, %%ecx" : : "d"(&z) );
asm( "mov 2, %%edx" : );
//int 80h

But I don't known how to insert 80h function call into this c++ code.

asm("int 80h") and asm("int 80h" : ) did not work. I am using clang++

OK, I actually solved this problem with this code which compiles succesfully:

char z[]="x";
int result;

asm( "mov 4, %%eax" : : : "eax" );
asm( "mov 1, %%ebx" : : : "ebx" );
asm( "mov %%edx, %%ecx" : : "d"(&z) : "ecx" );
asm( "mov 2, %%edx" : : : "edx" );
asm( "int $0x80" : );

But after executing I received segmentation fault error. I'm also receiving this message with -fsanitize=undefined,address flag:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==6068==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000004   (pc 0x558c9691bb24 bp 0x7ffde7b2e180 sp 0x7ffde7b2e0c0 T0)
==6068==The signal is caused by a READ memory access.
==6068==Hint: address points to the zero page.
#0 0x558c9691bb23  (/notroot/Documents/asmcheckcpp.e+0x137b23)
#1 0x7faa9eb49ce2  (/usr/lib/libc.so.6+0x23ce2)
#2 0x558c9680311d  (/notroot/Documents/asmcheckcpp.e+0x1f11d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/notroot/Documents/asmcheckcpp.e+0x137b23) 
==6068==ABORTING

I also debugged it with gdb so I knew that this program is crushing on this line:

asm( "mov 4, %%eax" : : : "eax" );

but I do not known why. - I already solved this, so this code:

cout << 'a' << endl;

char z[]="x";

asm( "mov $4, %%eax \n"
   "mov $1, %%ebx \n"
   "mov $2, %%edx \n"
   "int $0x80"
   :
   : "ecx"(&z)
   : "eax", "ebx", "edx" );

cout << 'a' << endl;

works but displays

a
a

not

a
xa

on the screen

  • Is there a reason you didn’t try asm(“int 80h”)? Or if you did, then why didn’t you include that in the question, along with why it doesn’t work? – prl May 26 '19 at 13:17
  • 2
    Guidelines for using inline assembly: 1. Don’t. 2 Don’t split a single sequence of assembly instructions into multiple asm statements. 3. Don’t use registers without telling the compiler about it. 4. Don’t load registers within the inline assembly; use operand constraints. – prl May 26 '19 at 13:21
  • @prl: GAS doesn't support trailing `h` suffix. You have to use `int $0x80`. Presumably clang's built-in assembler is the same. But yeah, this code is hilariously broken. I found a duplicate that shows how to use it *mostly* correctly. – Peter Cordes May 26 '19 at 15:06
  • @Roman: like prl said, you can't use separate asm statements for each instruction; those all *need* to be part of the same asm statement, like in the linked duplicate. (Or better, use input and output constraints so the only actual inline asm is `"int $0x80"`) – Peter Cordes May 26 '19 at 16:46
  • To actually debug if you're curious why it crashed, you need to switch your debugger to disassembly, not source, to see how your inline asm mixed with compiler-generated asm. Oh, NVM, no you don't. **`mov 4, %%eax` is a load from absolute address 4**. You wanted `$4` to have `4` as an immediate, not a memory address. – Peter Cordes May 26 '19 at 16:56
  • After adding $ befor each number code don't crash but... displays nothing... – Roman Kwaśniewski May 26 '19 at 17:07
  • You can't just make stuff up and hope it works. See the linked duplicate for a working example. `"ecx" (z)` gives the compiler the option of 3 constraints: `"c"` (the ECX register), `"x"` (any XMM register), or `"e"` (32-bit signed integer constant that can e.g. fit into an immediate for x86-64.) https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html – Peter Cordes May 26 '19 at 18:37
  • `/notroot/Documents/asmcheckcpp.e` are you running this on Windows Subsystem for Linux? Probably not because it doesn't support `int 0x80` and would segfault. But anyway, run your program under GDB and single-step the disassembly (not the C source), and/or run it under `strace` to trace system calls. Make sure you're building a 32-bit executable (`-m32`) otherwise pointers don't fit in 32-bit regs and you get `-EFAULT` with no output. Same thing if ECX doesn't hold a valid pointer for other reasons. – Peter Cordes May 26 '19 at 18:38

0 Answers0