Skip to content

Instantly share code, notes, and snippets.

@Stfort52
Last active October 30, 2023 11:46
Show Gist options
  • Save Stfort52/3e37fe90b0de04cc46db62ff4449ef9e to your computer and use it in GitHub Desktop.
Save Stfort52/3e37fe90b0de04cc46db62ff4449ef9e to your computer and use it in GitHub Desktop.
inline assembly snippets for pintOS
/**
* @brief Get a user byte
*
* @param uaddr user address to get byte from
* @return char user byte obtained, can be -1 on segfault.
*
* please note that it's impossible to distinguish between real -1 and segment -1,
* outside of this function's context.
*/
static char
get_user_byte (const uint8_t *uaddr)
{
int result;
asm ("movl $1f, %0; movzbl %1, %0; 1:"
: "=&a" (result) : "m" (*uaddr));
return result;
}
/**
* @brief Get a user dword
*
* @param uaddr user address to get byte from
* @return int user dword obtained, can be -1 on segfault.
*
* please note that it's impossible to distinguish between real -1 and segment -1,
* outside of this function's context.
*/
static int
get_user_dword (const uint32_t *uaddr)
{
int result;
asm ("movl $1f, %0; movl %1, %0; 1:"
: "=&a" (result) : "m" (*uaddr));
return result;
}
/**
* @brief Get the user string
*
* @param uaddr user address to copy from
* @param kaddr kernel address to copy to
* @param length maximum copy length
* @return true succeeded to get user string
* @return false segmentation fault occured
*
* please note that `rep` prefixes check for ecx == 0 before they decrement.
*/
static bool
get_user_str (char *uaddr, char *kaddr, size_t length)
{
int result;
asm ("cld; movl $1f, %0; rep movsb; movl $0, %%eax; 1:"
: "=&a" (result), "+S" (uaddr), "+D" (kaddr), "+c" (length) : : "memory");
return result == 0;
}
/**
* @brief Put string to userland
*
* @param uaddr user address to copy to
* @param kaddr kernel address to copy from
* @param length maximum copy length
* @return true succeeded to put string to userland
* @return false segmentation fault occured
*
* please note that `rep` prefixes check for ecx == 0 before they decrement.
*/
static bool
put_user_str (char *uaddr, char *kaddr, size_t length)
{
int result;
asm("cld; movl $1f, %0; rep movsb; movl $0, %%eax; 1:"
: "=&a" (result), "+D" (uaddr), "+S" (kaddr), "+c" (length) : : "memory");
return result == 0;
}
/**
* @brief scan user string, finding byte. similar to strchr()
*
* @param uaddr user address to start searching
* @param byte the byte to search
* @param maxlen maximum search length
* @return char* pointer to the byte found. NULL if not found. -1 on segmentation fault
*
* please note that `loop` instructions, unlike `rep` instructions, decrement eax before they check.
* using scasb will really simplify this into a simple `cld; repne scasb` but scans are designed to work with eax/ax/al.
*/
static char *
scan_user_str (char *uaddr, const uint8_t byte, size_t maxlen)
{
char * result;
asm("movl $1f, %0; test %%ecx, %%ecx; jz 3f; \n" //if maxlen == 0 then GOTO 3f; fi
"2: movzbl (%%esi), %%edx; cmp %%edx, %%ebx; jz 4f; inc %%esi; loop 2b;\n" //while(maxlen) if *uaddr == byte then GOTO 4f; else then uaddr++; maxlen--; fi
"3: xor %%eax, %%eax; jmp 1f; \n" //return 0;
"4: movl %%esi, %%eax; 1:" //return uaddr;
: "=&a" (result), "+S" (uaddr), "+c" (maxlen): "b"(byte) : "memory", "edx");
return result;
}
/**
* @brief copy string from userland to kernel, stop on meeting byte.
*
* @param uaddr user address to copy from
* @param kaddr kernel address to copy to
* @param byte terminator byte
* @param maxlen maximum size to copy
* @return size_t size actually copied, including the byte found. -1 on segmentation fault
*
* please note that `loop` instructions, unlike `rep` instructions, decrement eax before they check.
* using scasb will really simplify this into a simple `cld; repne scasb` but scans are designed to work with eax/ax/al.
*/
static size_t
scan_copy_user_str (char *uaddr, char *kaddr, const uint8_t byte, size_t maxlen)
{
size_t result, leftover;
asm("movl $1f, %0; test %%ecx, %%ecx; jz 1f; \n" //if maxlen == 0 then goto 1f; fi
"2: movzbl (%%esi), %%edx; movb %%dl, (%%edi); cmp %%edx, %%ebx; jz 3f; \n"
"inc %%esi; inc %%edi; loop 2b; jmp 1f; \n" // while(maxlen) *kaddr = *uaddr; if *uaddr == byte then GOTO 3f; else then uaddr++; kaddr++; maxlen--; fi GOTO 1f;
"3: dec %%ecx; 1:" //dec maxlen;
: "=&a" (result), "+S" (uaddr), "+D" (kaddr), "=c" (leftover)
: "c" (maxlen), "b"(byte) : "memory", "edx");
return result == 0xffffffff ? -1 : maxlen - leftover;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment