В вашем коде есть признаки того, что вы, возможно, использовали учебник Linux при создании кода для OS / X (BSD). Linux и OS / X отличаются соглашениями SYSCALL . В 32-битных программах OS / X для int 0x80
требуются параметры (за исключением того, что syscall в EAX ) передается в стеке.
Важные вещи, о которых нужно знать с помощью 32 -бит SYSCALL s через int 0x80
в OS / X:
blockquote>
- аргументы, переданные в стек, нажатые справа налево
- вы должны выделить дополнительные 4 байта ( DWORD ) в стеке после того, как вы нажмете все аргументы
- номер syscall в регистре eax
- вызов прерыванием 0x80
После нажатия аргументов в стеке в обратном порядке для
int 0x80
вы должны выделить дополнительные 4 байта ( DWORD ), в стеке. Значение в этой ячейке памяти в стеке не имеет значения. Это требование является артефактом из старого соглашения UNIX .Список номеров SYSCALL и их параметров можно найти в APPLE файлы заголовков . Вам понадобятся эти SYSCALL s:
blockquote>1 AUE_EXIT ALL { void exit(int rval); } 3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); } 4 AUE_NULL ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); }
Я прокомментировал некоторый пример кода, который будет похож по функциональности на то, что вы, возможно, были пытающихся достичь:
section .data ;New line string NEWLINE: db 0xa, 0xd LENGTH: equ $-NEWLINE section .bss INPT: resd 1 global _start section .text _start: and esp, -16 ; Make sure stack is 16 byte aligned at program start ; not necessary in this example since we don't call ; external functions that conform to the OS/X 32-bit ABI push dword 1 ; Read 1 character push dword INPT ; Input buffer push dword 0 ; Standard input = FD 0 mov eax, 3 ; syscall sys_read sub esp, 4 ; Extra 4 bytes on stack needed by int 0x80 int 0x80 add esp, 16 ; Restore stack push dword 1 ; Print 1 character push dword INPT ; Output buffer = buffer we read characters into push dword 1 ; Standard output = FD 1 mov eax, 4 ; syscall sys_write sub esp, 4 ; Extra 4 bytes on stack needed by int 0x80 int 0x80 add esp, 16 ; Restore stack push dword LENGTH ; Number of characters to write push dword NEWLINE ; Write the data in the NEWLINE string push dword 1 ; Standard output = FD 1 mov eax, 4 ; syscall sys_write sub esp, 4 ; Extra 4 bytes on stack needed by int 0x80 int 0x80 add esp, 16 ; Restore stack push dword 0 ; Return value from program = 0 mov eax, 1 ; syscall sys_exit sub esp, 4 ; Extra 4 bytes on stack needed by int 0x80 int 0x80
and esp, -16
необходимо, только если вам нужно выровнять стек с 16-байтовой границей в качестве базовой линии для будущих операций стека. Если вы намереваетесь вызывать внешние функции, которые соответствуют OS / X 32-битовому ABI , ожидается, что стек будет выровнен по 16 байт непосредственно перед функцией CALL . Это выравнивание не требуется для системных вызовов черезint 0x80
.Вы должны иметь возможность собирать и связывать его с:
nasm -f macho32 test.asm -o test.o ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem
И запустите его с помощью:
./test
Да. В .NET есть два типа типов: ссылочные типы и типы значений.
Типы ссылок (обычно классы) всегда упоминаются ссылками, поэтому они поддерживают null без какой-либо дополнительной работы. Это означает, что если тип переменной является ссылочным типом, переменная автоматически становится ссылкой.
Типы значений (например, int) по умолчанию не имеют понятия нуля. Тем не менее, есть обертка для них под названием Nullable. Это позволяет вам инкапсулировать ненулевой тип значения и включать нулевую информацию.
Использование немного отличается, хотя.
// Both of these types mean the same thing, the ? is just C# shorthand.
private void Example(int? arg1, Nullable<int> arg2)
{
if (arg1.HasValue)
DoSomething();
arg1 = null; // Valid.
arg1 = 123; // Also valid.
DoSomethingWithInt(arg1); // NOT valid!
DoSomethingWithInt(arg1.Value); // Valid.
}
Я думаю, что ближайший эквивалент C # int*
будет ref int?
. Потому что ref int?
позволяет вызываемому методу передавать значение обратно вызывающему методу.
int*
ref int?
Вы можете использовать NullableValueTypes (например, int?) Для этого. Код будет выглядеть так:
private void Example(int? arg1, int? arg2)
{
if(!arg1.HasValue)
{
//do something
}
if(!arg2.HasValue)
{
//do something else
}
}
Из C # 2.0:
private void Example(int? arg1, int? arg2)
{
if(arg1 == null)
{
//do something
}
if(arg2 == null)
{
//do something else
}
}
На вопрос ОП уже получен хороший ответ, но заголовок достаточно широк, так что я думаю, что он выигрывает от следующего учебника:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace consolePlay
{
class Program
{
static void Main(string[] args)
{
Program.test(new DateTime());
Program.test(null);
//Program.test(); // <<< Error.
// "No overload for method 'test' takes 0 arguments"
// So don't mistake nullable to be optional.
Console.WriteLine("Done. Return to quit");
Console.Read();
}
static public void test(DateTime? dteIn)
{
Console.WriteLine("#" + dteIn.ToString() + "#");
}
}
}
выход:
#1/1/0001 12:00:00 AM#
##
Done. Return to quit
Начиная с C # 2.0, вы можете использовать универсальный тип Nullable Nullable, а в C # есть условное обозначение типа, за которым следует?
, например
private void Example(int? arg1, int? arg2)
{
if(arg1 == null)
{
//do something
}
if(arg2 == null)
{
//do something else
}
}
Вы можете использовать 2 способа: int? или Nullable, оба имеют одинаковое поведение. Вы можете сделать микс без проблем, но лучше сделать код максимально чистым.
Вариант 1 (с?):
private void Example(int? arg1, int? arg2)
{
if (arg1.HasValue)
{
//do something
}
if (arg1.HasValue)
{
//do something else
}
}
Вариант 2 (с нулевым значением):
private void Example(Nullable<int> arg1, Nullable<int> arg2)
{
if (arg1.HasValue)
{
//do something
}
if (arg1.HasValue)
{
//do something else
}
}
В C # 4.0 появился новый способ сделать то же самое с большей гибкостью в этом случае платформа предлагает необязательные параметры со значениями по умолчанию , таким образом, вы можете установить значение по умолчанию, если метод вызывается без всех параметров.
Вариант 3 (со значениями по умолчанию)
private void Example(int arg1 = 0, int arg2 = 1)
{
//do something else
}